Buradaki diğer cevapların eleştirisi:
Bu cevapların hiçbiri eşit boyutta değil, hepsi sonunda bir runt parçası bırakıyor, bu yüzden tamamen dengeli değiller. İşi dağıtmak için bu işlevleri kullanıyorsanız, birinin diğerinden önce bitirmesi olasılığını yerleşik hale getirmişsinizdir, bu yüzden diğerleri çok çalışmaya devam ederken hiçbir şey yapmadan etrafta oturacaktır.
Örneğin, mevcut en iyi yanıt şununla biter:
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74]]
Sonunda sadece bu işten nefret ediyorum!
Diğerleri gibi list(grouper(3, xrange(7)))
, ve chunk(xrange(7), 3)
de dönüp: [(0, 1, 2), (3, 4, 5), (6, None, None)]
. None
Nakarat doldurma ve bence oldukça zarafetsiz edilir. Tekrarlanabilirleri eşit olarak parçalamazlar.
Bunları neden daha iyi bölemiyoruz?
Çözümlerim
İşte (yerine Python 3'te Not üretiminde kullanılan olduğunuz bir fonksiyonu uyarlanan dengeli bir çözüm, var xrange
olan range
):
def baskets_from(items, maxbaskets=25):
baskets = [[] for _ in xrange(maxbaskets)] # in Python 3 use range
for i, item in enumerate(items):
baskets[i % maxbaskets].append(item)
return filter(None, baskets)
Ve bir listeye koyarsanız aynı şeyi yapan bir jeneratör oluşturdum:
def iter_baskets_from(items, maxbaskets=3):
'''generates evenly balanced baskets from indexable iterable'''
item_count = len(items)
baskets = min(item_count, maxbaskets)
for x_i in xrange(baskets):
yield [items[y_i] for y_i in xrange(x_i, item_count, baskets)]
Ve son olarak, yukarıdaki tüm işlevlerin (verilen gibi) bitişik bir sırayla öğeleri döndürdüğünü gördüğüm için:
def iter_baskets_contiguous(items, maxbaskets=3, item_count=None):
'''
generates balanced baskets from iterable, contiguous contents
provide item_count if providing a iterator that doesn't support len()
'''
item_count = item_count or len(items)
baskets = min(item_count, maxbaskets)
items = iter(items)
floor = item_count // baskets
ceiling = floor + 1
stepdown = item_count % baskets
for x_i in xrange(baskets):
length = ceiling if x_i < stepdown else floor
yield [items.next() for _ in xrange(length)]
Çıktı
Test etmek için:
print(baskets_from(xrange(6), 8))
print(list(iter_baskets_from(xrange(6), 8)))
print(list(iter_baskets_contiguous(xrange(6), 8)))
print(baskets_from(xrange(22), 8))
print(list(iter_baskets_from(xrange(22), 8)))
print(list(iter_baskets_contiguous(xrange(22), 8)))
print(baskets_from('ABCDEFG', 3))
print(list(iter_baskets_from('ABCDEFG', 3)))
print(list(iter_baskets_contiguous('ABCDEFG', 3)))
print(baskets_from(xrange(26), 5))
print(list(iter_baskets_from(xrange(26), 5)))
print(list(iter_baskets_contiguous(xrange(26), 5)))
Hangi çıktılar:
[[0], [1], [2], [3], [4], [5]]
[[0], [1], [2], [3], [4], [5]]
[[0], [1], [2], [3], [4], [5]]
[[0, 8, 16], [1, 9, 17], [2, 10, 18], [3, 11, 19], [4, 12, 20], [5, 13, 21], [6, 14], [7, 15]]
[[0, 8, 16], [1, 9, 17], [2, 10, 18], [3, 11, 19], [4, 12, 20], [5, 13, 21], [6, 14], [7, 15]]
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14], [15, 16, 17], [18, 19], [20, 21]]
[['A', 'D', 'G'], ['B', 'E'], ['C', 'F']]
[['A', 'D', 'G'], ['B', 'E'], ['C', 'F']]
[['A', 'B', 'C'], ['D', 'E'], ['F', 'G']]
[[0, 5, 10, 15, 20, 25], [1, 6, 11, 16, 21], [2, 7, 12, 17, 22], [3, 8, 13, 18, 23], [4, 9, 14, 19, 24]]
[[0, 5, 10, 15, 20, 25], [1, 6, 11, 16, 21], [2, 7, 12, 17, 22], [3, 8, 13, 18, 23], [4, 9, 14, 19, 24]]
[[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20], [21, 22, 23, 24, 25]]
Bitişik jeneratörün diğer ikisi ile aynı uzunluk modellerinde parçalar sağladığına, ancak öğelerin hepsinin sırayla olduğuna ve ayrı elemanların bir listesini bölebileceği kadar eşit olarak bölünmüş olduğuna dikkat edin.