Bagaimana cara membuat for
loop atau daftar pemahaman sehingga setiap iterasi memberi saya dua elemen?
l = [1,2,3,4,5,6]
for i,k in ???:
print str(i), '+', str(k), '=', str(i+k)
Keluaran:
1+2=3
3+4=7
5+6=11
Bagaimana cara membuat for
loop atau daftar pemahaman sehingga setiap iterasi memberi saya dua elemen?
l = [1,2,3,4,5,6]
for i,k in ???:
print str(i), '+', str(k), '=', str(i+k)
Keluaran:
1+2=3
3+4=7
5+6=11
Jawaban:
Anda memerlukan pairwise()
(atau grouped()
) implementasi.
Untuk 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)
Atau, lebih umum:
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)
Di Python 3, Anda bisa mengganti izip
dengan zip()
fungsi bawaan, dan lepaskanimport
.
Semua kredit untuk martineau untuk jawaban atas pertanyaan saya , saya telah menemukan ini sangat efisien karena hanya mengulangi sekali dalam daftar dan tidak membuat daftar yang tidak perlu dalam proses.
NB : Ini tidak harus bingung dengan pairwise
resep dalam itertools
dokumentasi Python sendiri , yang menghasilkan s -> (s0, s1), (s1, s2), (s2, s3), ...
, seperti yang ditunjukkan oleh @ lazyr dalam komentar.
Tambahan kecil untuk mereka yang ingin melakukan pengecekan ketik dengan mypy pada 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
fungsi resep dengan nama yang sama. Tentu saja milikmu lebih cepat ...
izip_longest()
bukan izip()
. Misalnya: list(izip_longest(*[iter([1, 2, 3])]*2, fillvalue=0))
-> [(1, 2), (3, 0)]
. Semoga ini membantu.
Anda perlu dua elemen, jadi
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)
Dimana:
data[0::2]
artinya membuat subset kumpulan elemen itu (index % 2 == 0)
zip(x,y)
membuat koleksi tuple dari koleksi x dan y elemen indeks yang sama.for i, j, k in zip(data[0::3], data[1::3], data[2::3]):
import
bukan salah satu dari mereka.
>>> 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
mengembalikan zip
objek dengan Python 3, yang tidak dapat disubkripsikan . Itu perlu dikonversi ke urutan ( list
,, tuple
dll) terlebih dahulu, tetapi "tidak bekerja" adalah sedikit peregangan.
Solusi sederhana.
l = [1, 2, 3, 4, 5, 6] untuk saya dalam kisaran (0, len (l), 2): mencetak 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))
untuk generator, dapat dengan mudah dimodifikasi untuk tupel yang lebih panjang.
Sementara semua jawaban yang digunakan zip
sudah benar, saya menemukan bahwa mengimplementasikan sendiri fungsionalitas itu mengarah ke kode yang lebih mudah dibaca:
def pairwise(it):
it = iter(it)
while True:
try:
yield next(it), next(it)
except StopIteration:
# no more elements in the iterator
return
Bagian ini it = iter(it)
memastikan bahwa it
sebenarnya merupakan iterator, bukan hanya iterable. Jika it
sudah merupakan iterator, baris ini adalah no-op.
Pemakaian:
for a, b in pairwise([0, 1, 2, 3, 4, 5]):
print(a + b)
it
hanya merupakan iterator dan bukan iterable. Solusi lain tampaknya bergantung pada kemungkinan untuk membuat dua iterator independen untuk urutan.
Saya harap ini akan menjadi cara yang lebih elegan untuk melakukannya.
a = [1,2,3,4,5,6]
zip(a[::2], a[1::2])
[(1, 2), (3, 4), (5, 6)]
Jika Anda tertarik dengan kinerja, saya melakukan tolok ukur kecil (menggunakan perpustakaan saya simple_benchmark
) untuk membandingkan kinerja solusi dan saya menyertakan fungsi dari salah satu paket saya: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)
Jadi, jika Anda menginginkan solusi tercepat tanpa dependensi eksternal, Anda mungkin harus menggunakan pendekatan yang diberikan oleh Johnysweb (pada saat penulisan ini adalah jawaban yang paling banyak dipilih dan diterima).
Jika Anda tidak keberatan dengan ketergantungan tambahan maka grouper
dari iteration_utilities
mungkin akan sedikit lebih cepat.
Beberapa pendekatan memiliki beberapa batasan, yang belum dibahas di sini.
Misalnya beberapa solusi hanya bekerja untuk urutan (yaitu daftar, string, dll.), Misalnya solusi Margus / pyanon / taskinoor yang menggunakan pengindeksan sementara solusi lain bekerja pada setiap iterable (yaitu urutan dan generator, iterator) seperti Johnysweb / mic_e / solusi saya.
Kemudian Johnysweb juga memberikan solusi yang berfungsi untuk ukuran selain 2 sedangkan jawaban lainnya tidak (oke, the iteration_utilities.grouper
juga memungkinkan pengaturan jumlah elemen ke "grup").
Lalu ada juga pertanyaan tentang apa yang harus terjadi jika ada jumlah elemen ganjil dalam daftar. Haruskah barang yang tersisa dibubarkan? Haruskah daftar itu diisi dengan empuk agar ukurannya rata? Haruskah barang yang tersisa dikembalikan sebagai tunggal? Jawaban lainnya tidak membahas hal ini secara langsung, namun jika saya tidak mengabaikan apa pun mereka semua mengikuti pendekatan bahwa item yang tersisa harus diberhentikan (kecuali untuk jawaban taskinoors - yang benar-benar akan meningkatkan Pengecualian).
Dengan grouper
Anda dapat memutuskan apa yang ingin Anda lakukan:
>>> 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)]
Gunakan zip
dan iter
perintah bersama:
Saya merasa solusi ini iter
cukup elegan:
it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]
Yang saya temukan di dokumentasi zip 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
Untuk menggeneralisasi ke N
elemen sekaligus:
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)
mengembalikan tuple dengan elemen berikutnya dari setiap iterable.
l[::2]
mengembalikan elemen ke-1, ke-3, ke-5, dll. dari daftar: tanda titik dua menunjukkan bahwa irisan dimulai di awal karena tidak ada angka di belakangnya, tanda titik dua hanya diperlukan jika Anda menginginkan langkah 'pada irisan '(dalam hal ini 2).
l[1::2]
melakukan hal yang sama tetapi dimulai pada elemen kedua daftar sehingga mengembalikan elemen ke-2, ke-4, ke-6, dll. dari daftar asli .
[number::number]
kerja sintaksis. sangat membantu bagi mereka yang tidak sering menggunakan python
Dengan membongkar:
l = [1,2,3,4,5,6]
while l:
i, k, *l = l
print(str(i), '+', str(k), '=', str(i+k))
Bagi siapa pun yang mungkin bisa membantu, berikut adalah solusi untuk masalah yang serupa tetapi dengan pasangan yang tumpang tindih (bukan pasangan yang saling eksklusif).
Dari dokumentasi 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)
Atau, lebih umum:
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)
Anda dapat menggunakan paket more_itertools .
import more_itertools
lst = range(1, 7)
for i, j in more_itertools.chunked(lst, 2):
print(f'{i} + {j} = {i+j}')
Saya perlu membagi daftar dengan nomor dan memperbaikinya seperti ini.
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]]
Ada banyak cara untuk melakukan itu. Sebagai contoh:
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)]
Berpikir bahwa ini adalah tempat yang baik untuk membagikan generalisasi saya tentang ini untuk n> 2, yang hanya merupakan jendela geser di atas iterable:
def sliding_window(iterable, n):
its = [ itertools.islice(iter, i, None)
for i, iter
in enumerate(itertools.tee(iterable, n)) ]
return itertools.izip(*its)
Menggunakan pengetikan sehingga Anda dapat memverifikasi data menggunakan alat analisis statis 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
Pendekatan sederhana:
[(a[i],a[i+1]) for i in range(0,len(a),2)]
ini berguna jika array Anda adalah dan Anda ingin mengulanginya secara berpasangan. Untuk beralih pada kembar tiga atau lebih, cukup ubah perintah langkah "rentang", misalnya:
[(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)]
(Anda harus berurusan dengan nilai berlebih jika panjang dan langkah array Anda tidak cocok)
Di sini kita dapat memiliki alt_elem
metode yang sesuai untuk loop Anda.
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)
Keluaran:
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)
Catatan: Solusi di atas mungkin tidak efisien mengingat operasi yang dilakukan di func.
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)