Преобразование списка в дублированный [дубликат]

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

151
задан Peter Mortensen 6 April 2015 в 19:47
поделиться

19 ответов

Вам нужна реализация pairwise() (или grouped()).

Для Python 2:

from itertools import izip

def pairwise(iterable):
    "s -> (s0, s1), (s2, s3), (s4, s5), ..."
    a = iter(iterable)
    return izip(a, a)

for x, y in pairwise(l):
   print "%d + %d = %d" % (x, y, x + y)

Или, в более общем смысле:

from itertools import izip

def grouped(iterable, n):
    "s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
    return izip(*[iter(iterable)]*n)

for x, y in grouped(l, 2):
   print "%d + %d = %d" % (x, y, x + y)

В Python 3 вы можете заменить izip на встроенную функцию zip() и сбросить import.

Весь кредит martineau за на его ответ на мой вопрос , я нашел, что это очень эффективно, поскольку он только повторяет один раз над списком и не создает лишних списков в процессе.

Примечание: это не следует путать с рецептом pairwise в собственной документации itertools Python , которая дает s -> (s0, s1), (s1, s2), (s2, s3), ..., как указано из @lazyr в комментариях.

180
ответ дан Community 20 August 2018 в 08:23
поделиться
  • 1
    Не путать с парной функцией, предложенной в разделе рецептов itertools , что дает s -> (s0,s1), (s1,s2), (s2, s3), ... – Lauritz V. Thaulow 22 March 2011 в 11:13
  • 2
    Это другое дело. Ваша версия дает только половину количества пар по сравнению с функцией рецепта itertools с тем же именем. Конечно, ваши быстрее ... – Sven Marnach 22 March 2011 в 11:22
  • 3
    А? Ваша функция и функция, о которой я говорил, делают разные вещи, и это было моим замечанием. – Lauritz V. Thaulow 22 March 2011 в 11:24
  • 4
    БЫТЬ ОСТОРОЖЕН! Использование этих функций ставит вас под угрозу не итерации по последним элементам итерации. Пример: список (сгруппированный ([1,2,3], 2)) & gt; & gt; & gt; & gt; & gt; [(1, 2)] .. когда вы ожидаете [(1,2), (3,)] – egafni 20 January 2013 в 20:48
  • 5
    @ Erik49: В случае, указанном в вопросе, было бы бессмысленно иметь «неполный» кортеж. Если вы хотите включить неполный кортеж, вы можете использовать izip_longest() вместо izip(). Например: list(izip_longest(*[iter([1, 2, 3])]*2, fillvalue=0)) - & gt; [(1, 2), (3, 0)]. Надеюсь это поможет. – Johnsyweb 21 January 2013 в 04:19
for (i, k) in zip(l[::2], l[1::2]):
    print i, "+", k, "=", i+k

zip(*iterable) возвращает кортеж со следующим элементом каждого итерабельного.

l[::2] возвращает элемент 1-го, 3-го, 5-го и т. д. списка: первая двоеточие указывает, что срез начинается с начала, потому что за ним нет номера, второй двоеточие требуется только, если вы хотите «шаг в срезе» (в этом случае 2).

l[1::2] делает то же самое, но начинается во втором элементе списков, поэтому он возвращает элемент 2-го, 4-го, 6-го и т. д. исходного списка.

9
ответ дан alexpinho98 20 August 2018 в 08:23
поделиться
  • 1
    Этот ответ уже дал Маргус два года назад. [Д0] stackoverflow.com/questions/5389507/… – cababunga 9 August 2013 в 02:04
  • 2
    1 для объяснения того, как работает синтаксис [number::number]. полезно для тех, кто не использует python часто – Alby 26 December 2013 в 23:33

Для любого, кому это может помочь, вот решение аналогичной проблемы, но с перекрывающимися парами (вместо взаимно исключающих пар).

Из документации Python itertools :

from itertools import izip

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

Или, в более общем смысле:

from itertools import izip

def groupwise(iterable, n=2):
    "s -> (s0,s1,...,sn-1), (s1,s2,...,sn), (s2,s3,...,sn+1), ..."
    t = tee(iterable, n)
    for i in range(1, n):
        for j in range(0, i):
            next(t[i], None)
    return izip(*t)
2
ответ дан Chris Malek 20 August 2018 в 08:23
поделиться

Мы также можем просто сделать список набором кортежей

l = [(1,2),(3,4)]
l.append((5,6))
for r,c in l:
   print r,c

:

1 2
3 4
5 6
0
ответ дан edW 20 August 2018 в 08:23
поделиться

Ну, вам нужен набор из 2 элементов, поэтому

data = [1,2,3,4,5,6]
for i,k in zip(data[0::2], data[1::2]):
    print str(i), '+', str(k), '=', str(i+k)

Где:

  • data[0::2] означает создание набора подмножеств элементов, которые (index % 2 == 0)
  • zip(x,y) создает набор кортежей из x и y, которые собирают одинаковые элементы индекса.
136
ответ дан Margus 20 August 2018 в 08:23
поделиться
  • 1
    Это также можно расширить, если требуется более двух элементов. Напр. for i, j, k in zip(data[0::3], data[1::3], data[2::3]): – lifebalance 26 January 2014 в 17:53
  • 2
    Настолько чище, чем тянуть импорт и определять функцию! – kmarsh 13 May 2014 в 21:19
  • 3
    @kmarsh: Но это работает только с последовательностями, функция работает на любом итерабельном; и это использует O (N) дополнительное пространство, функция не работает; с другой стороны, это, как правило, быстрее. Есть веские причины выбрать тот или другой; страх import не является одним из них. – abarnert 3 August 2014 в 13:20

Хотя все ответы с использованием zip верны, я обнаружил, что реализация самой функции приводит к более читаемому коду:

def pairwise(it):
    it = iter(it)
    while True:
        yield next(it), next(it)

Часть it = iter(it) гарантирует, что it на самом деле является итератор, а не просто итеративный. Если it уже является итератором, эта строка не работает.

Использование:

for a, b in pairwise([0, 1, 2, 3, 4, 5]):
    print(a + b)
26
ответ дан mic_e 20 August 2018 в 08:23
поделиться
  • 1
    Это решение позволяет обобщить размер кортежей & gt; 2 – guilloptero 28 May 2015 в 08:27
  • 2
    Очень элегантное и обобщающее решение. – Drunken Master 23 July 2015 в 13:59
  • 3
    Это решение также работает, если it является только итератором, а не итерируемым. Другие решения, похоже, полагаются на возможность создания двух независимых итераторов для последовательности. – skyking 4 September 2015 в 09:32
  • 4
    Я нашел этот подход в stackoverflow.com/a/16815056/2480481 , прежде чем увидеть этот ответ. Чище, проще, чем иметь дело с zip (). – erm3nda 22 June 2017 в 18:34
  • 5
    Мне нравится, что это позволяет избежать использования памяти в три раза в качестве принятого ответа. – Kentzo 13 August 2018 в 23:15

Если вы заинтересованы в производительности, я сделал небольшой ориентир для сравнения производительности решений, и я включил функцию из одного из моих пакетов: iteration_utilities.grouper

def Johnsyweb(l):
    def pairwise(iterable):
        "s -> (s0, s1), (s2, s3), (s4, s5), ..."
        a = iter(iterable)
        return zip(a, a)

    for x, y in pairwise(l):
        pass

def Margus(data):
    for i, k in zip(data[0::2], data[1::2]):
        pass

def pyanon(l):
    list(zip(l,l[1:]))[::2]

def taskinoor(l):
    for i in range(0, len(l), 2):
        l[i], l[i+1]

def mic_e(it):
    def pairwise(it):
        it = iter(it)
        while True:
            try:
                yield next(it), next(it)
            except StopIteration:
                return

    for a, b in pairwise(it):
        pass

def MSeifert(it):
    for item1, item2 in grouper(it, 2):
        pass

from iteration_utilities import grouper
from simple_benchmark import benchmark_random_list

b = benchmark_random_list(
    [Johnsyweb, Margus, pyanon, taskinoor, mic_e, MSeifert],
    sizes=[2**i for i in range(1, 20)])

b.plot_both(relative_to=MSeifert)

Windows 10 64-разрядный Anaconda Python 3.6

Итак, если вам нужно самое быстрое решение без внешних зависимостей, вам, вероятно, следует просто использовать

Если вы не возражаете против дополнительной зависимости, то grouper из iteration_utilities, вероятно, будет немного быстрее, если вы не возражаете против дополнительной зависимости. .

Дополнительные мысли

Некоторые из подходов имеют некоторые ограничения, которые здесь не обсуждались.

Например, несколько решений работают только для последовательностей ( это списки, строки и т. д.), например решения Margus / pyanon / taskinoor, которые используют индексирование, в то время как другие решения работают над любым итерационным (то есть последовательностями и генераторами, итераторами), такими как решения Johnysweb / mic_e / my.

Затем Johnysweb также pr ovided решение, которое работает для других размеров, чем 2, в то время как другие ответы не соответствуют (хорошо, iteration_utilities.grouper также позволяет установить количество элементов в «группу»).

Затем возникает вопрос о том, что должно произойти, если в списке есть нечетное число элементов. Должен ли оставшийся пункт быть уволен? Должен ли список быть дополнен, чтобы сделать его даже размером? Должен ли оставшийся элемент быть возвращен как единый? Другой ответ не затрагивает эту точку напрямую, однако, если я не упускаю из виду что-либо, все они следуют подходу, согласно которому оставшийся элемент должен быть уволен (за исключением ответа на запрос, который фактически вызовет исключение).

С помощью grouper вы можете решить, что вы хотите сделать:

>>> from iteration_utilities import grouper

>>> list(grouper([1, 2, 3], 2))  # as single
[(1, 2), (3,)]

>>> list(grouper([1, 2, 3], 2, truncate=True))  # ignored
[(1, 2)]

>>> list(grouper([1, 2, 3], 2, fillvalue=None))  # padded
[(1, 2), (3, None)]
7
ответ дан MSeifert 20 August 2018 в 08:23
поделиться

Название этого вопроса вводит в заблуждение, похоже, вы ищете последовательные пары, но если вы хотите перебрать множество всех возможных пар, это будет работать:

for i,v in enumerate(items[:-1]):
        for u in items[i+1:]:
0
ответ дан Ofek Ron 20 August 2018 в 08:23
поделиться

Ближе всего к написанному вами коду:

l = [1,2,3,4,5,6]

for i,k in zip(l[::2], l[1::2]):
    print(str(i), '+', str(k), '=', str(i+k))

Выход:

1+2=3
3+4=7
5+6=11
3
ответ дан ox. 20 August 2018 в 08:23
поделиться
>>> l = [1,2,3,4,5,6]

>>> zip(l,l[1:])
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

>>> zip(l,l[1:])[::2]
[(1, 2), (3, 4), (5, 6)]

>>> [a+b for a,b in zip(l,l[1:])[::2]]
[3, 7, 11]

>>> ["%d + %d = %d" % (a,b,a+b) for a,b in zip(l,l[1:])[::2]]
['1 + 2 = 3', '3 + 4 = 7', '5 + 6 = 11']
55
ответ дан pyanon 20 August 2018 в 08:23
поделиться
  • 1
    – Hamid Rohani 6 February 2017 в 15:04
  • 2
    @HamidRohani zip возвращает объект zip в Python 3, который не подлежит расшифровке. Сначала его нужно преобразовать в последовательность (list, tuple и т. Д.), Но "не работает & quot; немного растягивается. – vaultah 25 February 2017 в 15:03

Используйте команды zip и iter вместе:

zip(*[iter(l)]*2)

, которые я нашел в документации Pipon 3 zip :

l = [1,2,3,4,5,6]

for i,j in zip(*[iter(l)]*2):
    print("{}+{}={}".format(str(i),str(j),str(i+j)))

, что приводит к:

1+2=3
3+4=7
5+6=11
2
ответ дан Rachid Riad 20 August 2018 в 08:23
поделиться

Здесь у нас может быть метод alt_elem, который может поместиться в ваш цикл for.

def alt_elem(list, index=2):
    for i, elem in enumerate(list, start=1):
        if not i % index:
           yield tuple(list[i-index:i])


a = range(10)
for index in [2, 3, 4]:
    print("With index: {0}".format(index))
    for i in alt_elem(a, index):
       print(i)

Выход:

With index: 2
(0, 1)
(2, 3)
(4, 5)
(6, 7)
(8, 9)
With index: 3
(0, 1, 2)
(3, 4, 5)
(6, 7, 8)
With index: 4
(0, 1, 2, 3)
(4, 5, 6, 7)

Примечание: выше решение может быть неэффективным с учетом операции, выполняемые в func.

0
ответ дан Sanket Sudake 20 August 2018 в 08:23
поделиться

вы можете использовать пакет more_itertools .

import more_itertools

lst = range(1, 7)
for i, j in more_itertools.chunked(lst, 2):
    print(f'{i} + {j} = {i+j}')
1
ответ дан Scott Ming 20 August 2018 в 08:23
поделиться

Простое решение.

l = [1, 2, 3, 4, 5, 6]

for i in range(0, len(l), 2):
    print str(l[i]), '+', str(l[i + 1]), '=', str(l[i] + l[i + 1])
50
ответ дан taskinoor 20 August 2018 в 08:23
поделиться
  • 1
  • 2
    что, если ваш список еще нет, и вы хотите просто показать последний номер, как есть? – Hans de Jong 16 October 2014 в 23:21
  • 3
    @HansdeJong не достал тебя. Пожалуйста, объясните немного больше. – taskinoor 19 October 2014 в 07:09
  • 4
    Благодарю. Я уже понял, как это сделать. Проблема в том, что если бы у вас был список, в котором не было даже количества чисел, оно получило бы индексную ошибку. Решил его попробовать: за исключением: – Hans de Jong 20 October 2014 в 10:39
  • 5
    Или ((l[i], l[i+1])for i in range(0, len(l), 2)) для генератора, можно легко изменить для более длинных кортежей. – Basel Shishani 29 July 2015 в 11:30

Извинения за опоздание. Я надеюсь, что это будет еще более элегантный способ сделать это.

a = [1,2,3,4,5,6]
zip(a[::2], a[1::2])

[(1, 2), (3, 4), (5, 6)]
11
ответ дан Vivek Srinivasan 20 August 2018 в 08:23
поделиться
  • 1
    Ты совсем не опаздываешь. Это всего лишь 5 лет. – multigoodverse 25 November 2016 в 11:45

Подумал, что это хорошее место, чтобы поделиться своим обобщением этого при n> 2, который является просто скользящим окном над итерируемым:

def sliding_window(iterable, n):
    its = [ itertools.islice(iter, i, None) 
            for i, iter
            in enumerate(itertools.tee(iterable, n)) ]                               

    return itertools.izip(*its)
0
ответ дан Yuval 20 August 2018 в 08:23
поделиться
0
ответ дан Ali Katkar 31 October 2018 в 07:07
поделиться
-1
ответ дан user391 31 October 2018 в 07:07
поделиться
0
ответ дан Vlad Bezden 31 October 2018 в 07:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: