Подтвердить что ты не робот

Итерация по всем двум элементам в списке

Как создать цикл for или список, чтобы каждая итерация давала мне два элемента?

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

for i,k in ???:
    print str(i), '+', str(k), '=', str(i+k)

Вывод:

1+2=3
3+4=7
5+6=11
4b9b3361

Ответ 1

Вам нужна 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.

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

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

Небольшое дополнение для тех, кто хотел бы выполнить проверку типов с помощью mypy на Python 3:

from typing import Iterable, Tuple, TypeVar

T = TypeVar("T")

def grouped(iterable: Iterable[T], n=2) -> Iterable[Tuple[T, ...]]:
    """s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), ..."""
    return zip(*[iter(iterable)] * n)

Ответ 2

Ну, вам нужен кортеж из 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, который объединяет те же элементы индекса.

Ответ 3

>>> 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']

Ответ 4

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

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])

Ответ 5

В то время как все ответы с использованием 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)

Ответ 6

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

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

[(1, 2), (3, 4), (5, 6)]

Ответ 7

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

from iteration_utilities import grouper
import matplotlib as mpl
from simple_benchmark import BenchmarkBuilder

bench = BenchmarkBuilder()

@bench.add_function()
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

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

@bench.add_function()
def pyanon(l):
    list(zip(l,l[1:]))[::2]

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

@bench.add_function()
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

@bench.add_function()
def MSeifert(it):
    for item1, item2 in grouper(it, 2):
        pass

bench.use_random_lists_as_arguments(sizes=[2**i for i in range(1, 20)])
benchmark_result = bench.run()
mpl.rcParams['figure.figsize'] = (8, 10)
benchmark_result.plot_both(relative_to=MSeifert)

enter image description here

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

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

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

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

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

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

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

С помощью 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)]

Ответ 8

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

Я нахожу это решение с помощью iter довольно элегантным:

it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]

Который я нашел в документации по Python 3 zip.

it = iter(l)
print(*(f'{u} + {v} = {u+v}' for u, v in zip(it, it)), sep='\n')

# 1 + 2 = 3
# 3 + 4 = 7
# 5 + 6 = 11

Чтобы обобщить до N элементов одновременно:

N = 2
list(zip(*([iter(l)] * N)))
# [(1, 2), (3, 4), (5, 6)]

Ответ 9

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-й и т.д. элементы в списке оригинал.

Ответ 10

Ближе всего к коду, который вы написали:

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

Ответ 11

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

В 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)

Ответ 12

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

import more_itertools

lst = range(1, 7)
for i, j in more_itertools.chunked(lst, 2):
    print(f'{i} + {j} = {i+j}')

Ответ 13

Мне нужно разделить список на число и исправить это следующим образом.

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

def divideByN(data, n):
        return [data[i*n : (i+1)*n] for i in range(len(data)//n)]  

>>> print(divideByN(l,2))
[[1, 2], [3, 4], [5, 6]]

>>> print(divideByN(l,3))
[[1, 2, 3], [4, 5, 6]]

Ответ 14

Подумал, что это хорошее место, чтобы поделиться своим обобщением этого при 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)

Ответ 15

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

for i,v in enumerate(items[:-1]):
        for u in items[i+1:]:

Ответ 16

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

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

вывод:

1 2
3 4
5 6

Ответ 17

Используя набор текста, вы можете проверить данные, используя инструмент статического анализа mypy:

from typing import Iterator, Any, Iterable, TypeVar, Tuple

T_ = TypeVar('T_')
Pairs_Iter = Iterator[Tuple[T_, T_]]

def legs(iterable: Iterator[T_]) -> Pairs_Iter:
    begin = next(iterable)
    for end in iterable:
        yield begin, end
        begin = end

Ответ 18

Упрощенный подход:

[(a[i],a[i+1]) for i in range(0,len(a),2)]

это полезно, если ваш массив - это, и вы хотите итерировать его по парам. Чтобы выполнить итерации по триплетам или более, просто измените команду шага "range", например:

[(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)]

(вам придется иметь дело с лишними значениями, если длина вашего массива и шаг не подходят)

Ответ 19

Здесь мы можем иметь метод 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.

Ответ 20

a_list = [1,2,3,4,5,6]
empty_list = [] 
for i in range(0,len(a_list),2):
   empty_list.append(a_list[i]+a_list[i+1])   
print(empty_list)