Відповіді:
Вам потрібна 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рецептом у власній itertoolsдокументації Python , яка дає результат 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)
s -> (s0,s1), (s1,s2), (s2, s3), ...
itertoolsфункцією рецепта. Звичайно, ваш швидше ...
izip_longest()замість izip(). Напр .: list(izip_longest(*[iter([1, 2, 3])]*2, fillvalue=0))-> [(1, 2), (3, 0)]. Сподіваюсь, це допомагає.
Ну вам потрібен кортеж з 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 однакових елементів індексу.for i, j, k in zip(data[0::3], data[1::3], data[2::3]):
importце не одна з них.
>>> 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']
zipповертає zipоб’єкт у Python 3, який не піддається підключенню. Спочатку його потрібно перетворити на послідовність ( list, tupleтощо), але "не працює" - це трохи розтягнення.
Просте рішення.
l = [1, 2, 3, 4, 5, 6]
для i в діапазоні (0, len (l), 2):
друку str (l [i]), '+', str (l [i + 1]), '=', str (l [i] + l [i + 1])
((l[i], l[i+1])for i in range(0, len(l), 2))для генератора, його можна легко змінити для довших кортежів.
Хоча всі відповіді з використанням zipправильних, я вважаю, що реалізація функціоналу самостійно призводить до більш читаного коду:
def pairwise(it):
it = iter(it)
while True:
try:
yield next(it), next(it)
except StopIteration:
# no more elements in the iterator
return
The it = iter(it) частині гарантує , що itнасправді итератор, а не просто ітерація. Якщо itвже є ітератором, цей рядок є неопераційним.
Використання:
for a, b in pairwise([0, 1, 2, 3, 4, 5]):
print(a + b)
itє лише ітератором, а не ітерабельним. Інші рішення, схоже, покладаються на можливість створення двох незалежних ітераторів для послідовності.
Я сподіваюся, що це буде ще більш елегантним способом зробити це.
a = [1,2,3,4,5,6]
zip(a[::2], a[1::2])
[(1, 2), (3, 4), (5, 6)]
Якщо ви зацікавлені в продуктивності, я зробив невеликий показник (використовуючи свою бібліотеку 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)
Тож, якщо ви хочете якнайшвидшого рішення без зовнішніх залежностей, вам, мабуть, слід просто скористатися підходом, запропонованим Johnysweb (на момент написання це найбільш відповідна і прийнята відповідь).
Якщо ви не заперечуєте додаткову залежність то grouperвід iteration_utilities, ймовірно , буде трохи швидше.
Деякі з підходів мають деякі обмеження, які тут не обговорювалися.
Наприклад, кілька рішень працюють лише для послідовностей (тобто списків, рядків тощо), наприклад, рішення Margus / pyanon / taskinoor, яке використовує індексацію, тоді як інші рішення працюють на будь-яких ітерабельних (тобто послідовностях та генераторах, ітераторах), таких як Johnysweb / mic_e / мої рішення.
Тоді Johnysweb також запропонував рішення, яке працює для інших розмірів, ніж 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)]
Використовуйте команди zipта iterкоманди разом:
Я вважаю це рішення iterдосить елегантним:
it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]
Що я знайшов у поштовій документації Python 3 .
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)]
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 та ін. початкового списку.
[number::number]працює синтаксис. корисно для тих, хто не використовує python часто
З розпакуванням:
l = [1,2,3,4,5,6]
while l:
i, k, *l = l
print(str(i), '+', str(k), '=', str(i+k))
Для когось це може допомогти, тут є рішення подібної проблеми, але з парами, що перекриваються (замість взаємовиключних пар).
З документації на itertools Python :
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)
ви можете використовувати пакет more_itertools .
import more_itertools
lst = range(1, 7)
for i, j in more_itertools.chunked(lst, 2):
print(f'{i} + {j} = {i+j}')
Мені потрібно розділити список на число і виправити так.
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]]
Є багато способів зробити це. Наприклад:
lst = [1,2,3,4,5,6]
[(lst[i], lst[i+1]) for i,_ in enumerate(lst[:-1])]
>>>[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
[i for i in zip(*[iter(lst)]*2)]
>>>[(1, 2), (3, 4), (5, 6)]
Використовуючи введення тексту, щоб ви могли перевірити дані за допомогою інструменту статичного аналізу 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
Спрощений підхід:
[(a[i],a[i+1]) for i in range(0,len(a),2)]
це корисно, якщо ваш масив є a і ви хочете повторити його парами. Для повторення трійки або більше просто змініть крок команди "діапазон", наприклад:
[(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)]
(вам доведеться мати справу із зайвими значеннями, якщо довжина масиву та крок не підходять)
Тут ми можемо мати alt_elemметод, який може вміститися у вашому циклі.
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)
Примітка: Наведене рішення може бути неефективним, враховуючи операції, що виконуються у функції.
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)