s = [1,2,3,4,5,6,7,8,9]
n = 3
zip(*[iter(s)]*n) # returns [(1,2,3),(4,5,6),(7,8,9)]
Nasıl zip(*[iter(s)]*n)çalışır? Daha ayrıntılı bir kodla yazılmış olsaydı nasıl görünürdü?
s = [1,2,3,4,5,6,7,8,9]
n = 3
zip(*[iter(s)]*n) # returns [(1,2,3),(4,5,6),(7,8,9)]
Nasıl zip(*[iter(s)]*n)çalışır? Daha ayrıntılı bir kodla yazılmış olsaydı nasıl görünürdü?
Yanıtlar:
iter()bir dizi üzerinde yineleyicidir. miktarı , yani her bir elemanın olduğu uzunluk [x] * nlistesini içeren bir liste üretir . işlev çağrısı için bir diziyi bağımsız değişkenlere dönüştürür. Bu nedenle, aynı yineleyiciyi 3 kez'e geçiriyorsunuz ve her seferinde yineleyiciden bir öğe çekiyor.nxnx*argzip()
x = iter([1,2,3,4,5,6,7,8,9])
print zip(x, x, x)
yield(= returns) kullandığında, bu öğeyi "tüketilmiş" olarak hayal edebilirsiniz. Dolayısıyla yineleyici bir sonraki çağrıldığında, bir sonraki "tüketilmemiş" öğeyi verir.
Diğer harika cevaplar ve yorumlar, argüman açma ve zip () rollerini iyi açıklar .
As Ignacio ve ujukatzel söz hakkından, sen geçmek zip()aynı yineleyici üç referanslar ve zip()sipariş-gelen yineleyici her referansta tamsayılar-3-dizilerini yapar:
1,2,3,4,5,6,7,8,9 1,2,3,4,5,6,7,8,9 1,2,3,4,5,6,7,8,9
^ ^ ^
^ ^ ^
^ ^ ^
Ve daha ayrıntılı bir kod örneği istediğiniz için:
chunk_size = 3
L = [1,2,3,4,5,6,7,8,9]
# iterate over L in steps of 3
for start in range(0,len(L),chunk_size): # xrange() in 2.x; range() in 3.x
end = start + chunk_size
print L[start:end] # three-item chunks
Değerlerini takip startve end:
[0:3) #[1,2,3]
[3:6) #[4,5,6]
[6:9) #[7,8,9]
FWIW, aşağıdaki map()ilk argümanla aynı sonucu elde edebilirsiniz None:
>>> map(None,*[iter(s)]*3)
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
Daha fazlası için zip()ve map(): http://muffinresearch.co.uk/archives/2007/10/16/python-transposing-lists-with-map-and-zip/
Bence tüm yanıtlarda gözden kaçan (muhtemelen yinelemelere aşina olanlar için açıktır), ancak diğerleri için o kadar açık olmayan bir şey -
Aynı yineleyiciye sahip olduğumuz için tüketilir ve kalan öğeler zip tarafından kullanılır. Öyleyse, örneğin yinelemeyi değil, listeyi kullanırsak.
l = range(9)
zip(*([l]*3)) # note: not an iter here, the lists are not emptied as we iterate
# output
[(0, 0, 0), (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 6, 6), (7, 7, 7), (8, 8, 8)]
Yineleyiciyi kullanarak değerleri açar ve yalnızca kalan kullanılabilir durumda kalır, bu nedenle zip için 0 tüketildiğinde 1 kullanılabilir ve ardından 2 vb. Çok ince bir şey, ama oldukça zekice !!!
iter(s) s için bir yineleyici döndürür.
[iter(s)]*n s için aynı yineleyicinin n katının bir listesini yapar.
Böylece, bunu yaparken zip(*[iter(s)]*n), sırayla listedeki üç yineleyiciden bir öğe çıkarır. Tüm yineleyiciler aynı nesne olduğundan, listeyi sadece n.
Zip'i bu şekilde kullanmak için bir tavsiye. Uzunluğu eşit olarak bölünemezse listenizi kısaltır. Bu sorunu çözmek için , doldurma değerlerini kabul edebiliyorsanız, itertools.izip_longest'i kullanabilirsiniz . Veya bunun gibi bir şey kullanabilirsiniz:
def n_split(iterable, n):
num_extra = len(iterable) % n
zipped = zip(*[iter(iterable)] * n)
return zipped if not num_extra else zipped + [iterable[-num_extra:], ]
Kullanım:
for ints in n_split(range(1,12), 3):
print ', '.join([str(i) for i in ints])
Baskılar:
1, 2, 3
4, 5, 6
7, 8, 9
10, 11
itertoolstariflerde belgelenmiştir : docs.python.org/2/library/itertools.html#recipes grouper . Tekerleği yeniden icat etmeye gerek yok
Yorumlayıcı veya piton neler olduğunu görmek için muhtemelen daha kolay olduğu ipythonile n = 2:
In [35]: [iter("ABCDEFGH")]*2
Out[35]: [<iterator at 0x6be4128>, <iterator at 0x6be4128>]
Yani, aynı yineleyici nesnesini işaret eden iki yineleyiciden oluşan bir listemiz var. Unutmayın iterbir nesne getirileri üzerinde yineleyici nesne ve bu senaryoda, aynı yineleyici nedeniyle iki kat *2piton sözdizimsel şeker. Yineleyiciler de yalnızca bir kez çalışır.
Bundan başka, zipIterables herhangi bir sayıda (alır sekansları olan Iterables ) ve giriş dizilerinin her birinin i'inci elemanından tuple oluşturur. Bizim durumumuzda her iki yineleyici de aynı olduğundan, zip, her 2 öğeli çıktı dizisi için aynı yineleyiciyi iki kez hareket ettirir.
In [41]: help(zip)
Help on built-in function zip in module __builtin__:
zip(...)
zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)]
Return a list of tuples, where each tuple contains the i-th element
from each of the argument sequences. The returned list is truncated
in length to the length of the shortest argument sequence.
Açma ( *) operatör olmasını sağlar yinelemeler bu durumda 2 öğeli bir tuple oluşturmak için yeterli girdi olmadığı kadar olan tükenmesi çalıştırmak.
Bu, herhangi bir değere genişletilebilir nve zip(*[iter(s)]*n)açıklandığı gibi çalışır.
*, bir nesneyi kopyalamak için sadece rahatlıktır. Skalarlarla ve ardından listelerle deneyin. Ayrıca denemek print(*zip(*[iter("ABCDEFG")]*2))vs print(*zip(*[iter("ABCDEFG"), iter("ABCDEFG")])). Ardından, iki ifadedeki yineleyici nesnelerin gerçekte ne olduğunu görmek için ikisini daha küçük adımlara ayırmaya başlayın.