كيف يمكنك تقسيم القائمة إلى أجزاء متساوية الحجم؟
سؤال
لدي قائمة ذات طول عشوائي، وأحتاج إلى تقسيمها إلى أجزاء متساوية الحجم والعمل عليها.هناك بعض الطرق الواضحة للقيام بذلك، مثل الاحتفاظ بعداد وقائمتين، وعندما تمتلئ القائمة الثانية، قم بإضافتها إلى القائمة الأولى وإفراغ القائمة الثانية للجولة التالية من البيانات، ولكن من المحتمل أن يكون هذا مكلفًا للغاية.
كنت أتساءل عما إذا كان لدى أي شخص حل جيد لهذا لقوائم بأي طول، على سبيل المثال.باستخدام المولدات.
كنت أبحث عن شيء مفيد في itertools
لكنني لم أجد أي شيء مفيد بشكل واضح.ربما فاتني ذلك، رغم ذلك.
سؤال ذو صلة: ما هي الطريقة الأكثر "بيثونية" للتكرار على قائمة في أجزاء؟
المحلول
وهنا المولدات التي تعطي مساحات تريد:
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
import pprint
pprint.pprint(list(chunks(range(10, 75), 10)))
[[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74]]
إذا كنت تستخدم بايثون 2، يجب عليك استخدام xrange()
بدلا من range()
:
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in xrange(0, len(l), n):
yield l[i:i + n]
وأيضا يمكنك ببساطة استخدام الفهم قائمة بدلا من كتابة وظيفة، على الرغم من انها فكرة جيدة لتغليف مثل هذه العمليات في وظائف اسمه بحيث التعليمات البرمجية أسهل للفهم. بيثون 3:
[l[i:i + n] for i in range(0, len(l), n)]
وبايثون 2 نسخة:
[l[i:i + n] for i in xrange(0, len(l), n)]
نصائح أخرى
إذا كنت تريد شيئا السوبر بسيط:
def chunks(l, n):
n = max(1, n)
return (l[i:i+n] for i in xrange(0, len(l), n))
استخدم range()
بدلا من xrange()
في حالة بيثون 3.X
ومباشرة من (القديمة) وثائق بيثون (وصفات لitertools):
from itertools import izip, chain, repeat
def grouper(n, iterable, padvalue=None):
"grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)
والإصدار الحالي، على النحو الذي اقترحه J.F.Sebastian:
#from itertools import izip_longest as zip_longest # for Python 2.x
from itertools import zip_longest # for Python 3.x
#from six.moves import zip_longest # for both (uses the six compat library)
def grouper(n, iterable, padvalue=None):
"grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
return zip_longest(*[iter(iterable)]*n, fillvalue=padvalue)
وأعتقد غيدو الوقت المصنفات عمل، وآلة العمل، وعملت، والعمل مرة أخرى.
وهذه الحلول تعمل ل[iter(iterable)]*n
(أو ما يعادلها في إصدار سابق) بإنشاء <م> واحدة م> مكرر، وأحيانا n
تتكرر في القائمة. izip_longest
ثم ينفذ بشكل فعال على بعد جولة روبن من "كل" مكرر. لأن هذا هو نفس مكرر، وتقدمت من قبل كل تلك الدعوة، مما أدى إلى كل هذا الرمز البريدي roundrobin توليد الصفوف (tuple) أحد البنود n
.
وأنا أعلم أن هذا هو نوع من العمر ولكن أنا لا لماذا لا أحد ذكر numpy.array_split
:
lst = range(50)
In [26]: np.array_split(lst,5)
Out[26]:
[array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),
array([20, 21, 22, 23, 24, 25, 26, 27, 28, 29]),
array([30, 31, 32, 33, 34, 35, 36, 37, 38, 39]),
array([40, 41, 42, 43, 44, 45, 46, 47, 48, 49])]
وأنا لا أحد بالدهشة استخدام iter
في شكل يومين حجة و>:
from itertools import islice
def chunk(it, size):
it = iter(it)
return iter(lambda: tuple(islice(it, size)), ())
وعرض توضيحي:
>>> list(chunk(range(14), 3))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13)]
وهذا يعمل مع أي iterable وينتج إخراج بتكاسل. فإنها ترجع الصفوف بدلا من التكرارات، ولكن أعتقد أن لديها الأناقة معينة مع ذلك. فإنه أيضا لا منصة، إذا كنت تريد الحشو، والاختلاف بسيط على ما سبق يكفي:
from itertools import islice, chain, repeat
def chunk_pad(it, size, padval=None):
it = chain(iter(it), repeat(padval))
return iter(lambda: tuple(islice(it, size)), (padval,) * size)
وعرض توضيحي:
>>> list(chunk_pad(range(14), 3))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, None)]
>>> list(chunk_pad(range(14), 3, 'a'))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 'a')]
ومثل الحلول المستندة إلى izip_longest
، وفوق دائما م> منصات. وبقدر ما أعرف، وليس هناك خط واحد أو اثنين itertools صفة لوظيفة أن <م> اختياريا م> منصات. من خلال الجمع بين النهجين أعلاه، هذا واحد يأتي جميلة قريبة:
_no_padding = object()
def chunk(it, size, padval=_no_padding):
if padval == _no_padding:
it = iter(it)
sentinel = ()
else:
it = chain(iter(it), repeat(padval))
sentinel = (padval,) * size
return iter(lambda: tuple(islice(it, size)), sentinel)
وعرض توضيحي:
>>> list(chunk(range(14), 3))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13)]
>>> list(chunk(range(14), 3, None))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, None)]
>>> list(chunk(range(14), 3, 'a'))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 'a')]
وأعتقد أن هذا هو أقصر chunker المقترحة التي تقدم الحشو اختياري.
وأما توماس Gandor <لأ href = "https://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks/22045226؟noredirect=1#comment93566337_22045226 "> لاحظ ، و سيتم إيقاف اثنين من chunkers الحشو بشكل غير متوقع إذا كانت تواجه سلسلة طويلة من القيم وسادة. وهنا الاختلاف النهائي الذي يعمل حول هذه المشكلة بطريقة معقولة:
_no_padding = object()
def chunk(it, size, padval=_no_padding):
it = iter(it)
chunker = iter(lambda: tuple(islice(it, size)), ())
if padval == _no_padding:
yield from chunker
else:
for ch in chunker:
yield ch if len(ch) == size else ch + (padval,) * (size - len(ch))
وعرض توضيحي:
>>> list(chunk([1, 2, (), (), 5], 2))
[(1, 2), ((), ()), (5,)]
>>> list(chunk([1, 2, None, None, 5], 2, None))
[(1, 2), (None, None), (5, None)]
وهنا هو مولد التي تعمل على iterables التعسفية:
def split_seq(iterable, size):
it = iter(iterable)
item = list(itertools.islice(it, size))
while item:
yield item
item = list(itertools.islice(it, size))
مثال:
>>> import pprint
>>> pprint.pprint(list(split_seq(xrange(75), 10)))
[[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, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74]]
def chunk(input, size):
return map(None, *([iter(input)] * size))
وبسيط وأنيق
l = range(1, 1000)
print [l[x:x+10] for x in xrange(0, len(l), 10)]
وأو إذا كنت تفضل:
chunks = lambda l, n: [l[x: x+n] for x in xrange(0, len(l), n)]
chunks(l, 10)
لقد رأيت إجابة Python-ish الأكثر روعة في ملف ينسخ من هذا السؤال:
from itertools import zip_longest
a = range(1, 16)
i = iter(a)
r = list(zip_longest(i, i, i))
>>> print(r)
[(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12), (13, 14, 15)]
يمكنك إنشاء n-tuple لأي n.لو a = range(1, 15)
, ، فتكون النتيجة:
[(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12), (13, 14, None)]
إذا تم تقسيم القائمة بالتساوي، فيمكنك استبدالها zip_longest
مع zip
, وإلا الثلاثي (13, 14, None)
سوف تضيع.تم استخدام Python 3 أعلاه.بالنسبة لبيثون 2، استخدم izip_longest
.
نقد الإجابات الأخرى هنا:
لا تحتوي أي من هذه الإجابات على أجزاء متساوية الحجم، بل تترك جميعها جزءًا صغيرًا في النهاية، لذا فهي ليست متوازنة تمامًا.إذا كنت تستخدم هذه الوظائف لتوزيع العمل، فقد بنيت في احتمال أن ينتهي أحدهم قبل الآخرين بفترة طويلة، لذلك سيجلس دون فعل أي شيء بينما يواصل الآخرون العمل الجاد.
على سبيل المثال، تنتهي الإجابة الحالية بـ:
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74]]
أنا فقط أكره هذا القزم في النهاية!
آخرون، مثل list(grouper(3, xrange(7)))
, ، و chunk(xrange(7), 3)
كلاهما يعود: [(0, 1, 2), (3, 4, 5), (6, None, None)]
.ال None
إنها مجرد حشوة، وغير أنيقة إلى حد ما في رأيي.إنهم لا يقومون بتقطيع العناصر التكرارية بالتساوي.
لماذا لا يمكننا تقسيم هذه بشكل أفضل؟
الحل الخاص بي (الحلول)
إليك حل متوازن، مقتبس من وظيفة استخدمتها في الإنتاج (لاحظ في Python 3 لاستبدال xrange
مع 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)
وقمت بإنشاء مولد يفعل الشيء نفسه إذا قمت بوضعه في القائمة:
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)]
وأخيرًا، بما أنني أرى أن جميع الوظائف المذكورة أعلاه تُرجع العناصر بترتيب متجاور (كما تم تقديمها):
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)]
انتاج |
لاختبارهم:
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)))
الذي يطبع:
[[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]]
لاحظ أن المولد المتجاور يوفر قطعًا بنفس أنماط الطول مثل المولدين الآخرين، ولكن العناصر كلها مرتبة، وهي مقسمة بالتساوي كما يمكن تقسيم قائمة من العناصر المنفصلة.
إذا كنت تعرف حجم القائمة:
def SplitList(mylist, chunk_size):
return [mylist[offs:offs+chunk_size] for offs in range(0, len(mylist), chunk_size)]
إذا كنت لا (مكرر):
def IterChunks(sequence, chunk_size):
res = []
for item in sequence:
res.append(item)
if len(res) >= chunk_size:
yield res
res = []
if res:
yield res # yield the last, incomplete, portion
في هذه الحالة الأخيرة، يمكن إعادة صياغة بطريقة أكثر جمالا إذا كان يمكنك أن تتأكد من أن تسلسل يحتوي دائما عددا كاملا من قطع من حجم معين (أي لا يوجد غير مكتملة قطعة الماضية).
إذا كان لديك حجم قطعة من 3 على سبيل المثال، يمكن أن تفعله:
zip(*[iterable[i::3] for i in range(3)])
المصدر: http://code.activestate.com/recipes/303060-group -a القائمة حيز متتابعة ن الصفوف /
وأود أن استخدام هذا الرقم عند ثابتة مقاسي قطعة استطيع ان اكتب، على سبيل المثال '3'، وسوف لا تتغير أبدا.
تولز مكتبة لديه وظيفة partition
لذلك:
from toolz.itertoolz.core import partition
list(partition(2, [1, 2, 3, 4]))
[(1, 2), (3, 4)]
أحب نسخة Python Doc التي اقترحتها Tzot و Jfsebastian كثيرًا ، ولكن لديها عيوبان:
- انها ليست واضحة جدا
- عادةً لا أريد قيمة تعبئة في الجزء الأخير
أنا أستخدم هذا كثيرًا في الكود الخاص بي:
from itertools import islice
def chunks(n, iterable):
iterable = iter(iterable)
while True:
yield tuple(islice(iterable, n)) or iterable.next()
تحديث:نسخة قطع كسول:
from itertools import chain, islice
def chunks(n, iterable):
iterable = iter(iterable)
while True:
yield chain([next(iterable)], islice(iterable, n-1))
في هذه المرحلة، أعتقد أننا بحاجة إلى مولد العودي, ، فقط في حالة...
في بيثون 2:
def chunks(li, n):
if li == []:
return
yield li[:n]
for e in chunks(li[n:], n):
yield e
في بيثون 3:
def chunks(li, n):
if li == []:
return
yield li[:n]
yield from chunks(li[n:], n)
أيضًا، في حالة الغزو الفضائي الضخم، أ مولد عودي مزين قد يصبح مفيدًا:
def dec(gen):
def new_gen(li, n):
for e in gen(li, n):
if e == []:
return
yield e
return new_gen
@dec
def chunks(li, n):
yield li[:n]
for e in chunks(li[n:], n):
yield e
ويمكنك أيضا استخدام get_chunks
ظيفة <أ href = على "HTTP : //utilspie.readthedocs.io "يختلط =" noreferrer "> utilspie
مكتبة النحو التالي:
>>> from utilspie import iterutils
>>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(iterutils.get_chunks(a, 5))
[[1, 2, 3, 4, 5], [6, 7, 8, 9]]
ويمكنك تثبيت utilspie
عبر نقطة:
sudo pip install utilspie
تنويه: انا خالق utilspie مكتبة م>
لقد كنت أشعر بالفضول بشأن أداء الأساليب المختلفة وهنا:
تم اختباره على بايثون 3.5.1
import time
batch_size = 7
arr_len = 298937
#---------slice-------------
print("\r\nslice")
start = time.time()
arr = [i for i in range(0, arr_len)]
while True:
if not arr:
break
tmp = arr[0:batch_size]
arr = arr[batch_size:-1]
print(time.time() - start)
#-----------index-----------
print("\r\nindex")
arr = [i for i in range(0, arr_len)]
start = time.time()
for i in range(0, round(len(arr) / batch_size + 1)):
tmp = arr[batch_size * i : batch_size * (i + 1)]
print(time.time() - start)
#----------batches 1------------
def batch(iterable, n=1):
l = len(iterable)
for ndx in range(0, l, n):
yield iterable[ndx:min(ndx + n, l)]
print("\r\nbatches 1")
arr = [i for i in range(0, arr_len)]
start = time.time()
for x in batch(arr, batch_size):
tmp = x
print(time.time() - start)
#----------batches 2------------
from itertools import islice, chain
def batch(iterable, size):
sourceiter = iter(iterable)
while True:
batchiter = islice(sourceiter, size)
yield chain([next(batchiter)], batchiter)
print("\r\nbatches 2")
arr = [i for i in range(0, arr_len)]
start = time.time()
for x in batch(arr, batch_size):
tmp = x
print(time.time() - start)
#---------chunks-------------
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
print("\r\nchunks")
arr = [i for i in range(0, arr_len)]
start = time.time()
for x in chunks(arr, batch_size):
tmp = x
print(time.time() - start)
#-----------grouper-----------
from itertools import zip_longest # for Python 3.x
#from six.moves import zip_longest # for both (uses the six compat library)
def grouper(iterable, n, padvalue=None):
"grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
return zip_longest(*[iter(iterable)]*n, fillvalue=padvalue)
arr = [i for i in range(0, arr_len)]
print("\r\ngrouper")
start = time.time()
for x in grouper(arr, batch_size):
tmp = x
print(time.time() - start)
نتائج:
slice
31.18285083770752
index
0.02184295654296875
batches 1
0.03503894805908203
batches 2
0.22681021690368652
chunks
0.019841909408569336
grouper
0.006506919860839844
[AA[i:i+SS] for i in range(len(AA))[::SS]]
وأين AA هو مجموعة، SS هو حجم قطعة. على سبيل المثال:
>>> AA=range(10,21);SS=3
>>> [AA[i:i+SS] for i in range(len(AA))[::SS]]
[[10, 11, 12], [13, 14, 15], [16, 17, 18], [19, 20]]
# or [range(10, 13), range(13, 16), range(16, 19), range(19, 21)] in py3
كود:
def split_list(the_list, chunk_size):
result_list = []
while the_list:
result_list.append(the_list[:chunk_size])
the_list = the_list[chunk_size:]
return result_list
a_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print split_list(a_list, 3)
والنتيجة:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
وهيه، الإصدار سطر واحد
In [48]: chunk = lambda ulist, step: map(lambda i: ulist[i:i+step], xrange(0, len(ulist), step))
In [49]: chunk(range(1,100), 10)
Out[49]:
[[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, 26, 27, 28, 29, 30],
[31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
[41, 42, 43, 44, 45, 46, 47, 48, 49, 50],
[51, 52, 53, 54, 55, 56, 57, 58, 59, 60],
[61, 62, 63, 64, 65, 66, 67, 68, 69, 70],
[71, 72, 73, 74, 75, 76, 77, 78, 79, 80],
[81, 82, 83, 84, 85, 86, 87, 88, 89, 90],
[91, 92, 93, 94, 95, 96, 97, 98, 99]]
def split_seq(seq, num_pieces):
start = 0
for i in xrange(num_pieces):
stop = start + len(seq[i::num_pieces])
yield seq[start:stop]
start = stop
والاستعمال:
seq = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for seq in split_seq(seq, 3):
print seq
ونسخة أكثر وضوحا آخر.
def chunkList(initialList, chunkSize):
"""
This function chunks a list into sub lists
that have a length equals to chunkSize.
Example:
lst = [3, 4, 9, 7, 1, 1, 2, 3]
print(chunkList(lst, 3))
returns
[[3, 4, 9], [7, 1, 1], [2, 3]]
"""
finalList = []
for i in range(0, len(initialList), chunkSize):
finalList.append(initialList[i:i+chunkSize])
return finalList
وبدون ان تدعو ليون () وهو امر جيد للقوائم كبيرة:
def splitter(l, n):
i = 0
chunk = l[:n]
while chunk:
yield chunk
i += n
chunk = l[i:i+n]
وهذا هو لiterables:
def isplitter(l, n):
l = iter(l)
chunk = list(islice(l, n))
while chunk:
yield chunk
chunk = list(islice(l, n))
ونكهة الوظيفية للأعلاه:
def isplitter2(l, n):
return takewhile(bool,
(tuple(islice(start, n))
for start in repeat(iter(l))))
وOR:
def chunks_gen_sentinel(n, seq):
continuous_slices = imap(islice, repeat(iter(seq)), repeat(0), repeat(n))
return iter(imap(tuple, continuous_slices).next,())
وOR:
def chunks_gen_filter(n, seq):
continuous_slices = imap(islice, repeat(iter(seq)), repeat(0), repeat(n))
return takewhile(bool,imap(tuple, continuous_slices))
وحل واحد أكثر
def make_chunks(data, chunk_size):
while data:
chunk, data = data[:chunk_size], data[chunk_size:]
yield chunk
>>> for chunk in make_chunks([1, 2, 3, 4, 5, 6, 7], 2):
... print chunk
...
[1, 2]
[3, 4]
[5, 6]
[7]
>>>
matplotlib.cbook قطع
وعلى سبيل المثال:
import matplotlib.cbook as cbook
segments = cbook.pieces(np.arange(20), 3)
for s in segments:
print s
>>> orange = range(1, 1001)
>>> otuples = list( zip(*[iter(orange)]*10))
>>> print(otuples)
[(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), ... (991, 992, 993, 994, 995, 996, 997, 998, 999, 1000)]
>>> olist = [list(i) for i in otuples]
>>> print(olist)
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ..., [991, 992, 993, 994, 995, 996, 997, 998, 999, 1000]]
>>>
وPython3
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
CHUNK = 4
[a[i*CHUNK:(i+1)*CHUNK] for i in xrange((len(a) + CHUNK - 1) / CHUNK )]
وعند هذه النقطة، وأعتقد أننا بحاجة إلى وظيفة غير معروفة، العودية إلزامية.
Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
chunks = Y(lambda f: lambda n: [n[0][:n[1]]] + f((n[0][n[1]:], n[1])) if len(n[0]) > 0 else [])
ومنذ الجميع هنا يتحدث عن التكرارات. boltons
ديه طريقة مثالية لهذا، ودعا <لأ href = "https://boltons.readthedocs.io/en /latest/iterutils.html#boltons.iterutils.chunked_iter "يختلط =" noreferrer "> iterutils.chunked_iter
.
from boltons import iterutils
list(iterutils.chunked_iter(list(range(50)), 11))
وإخراج:
[[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, 26, 27, 28, 29, 30, 31, 32],
[33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43],
[44, 45, 46, 47, 48, 49]]
ولكن إذا كنت لا تريد أن تكون رحمة على الذاكرة، يمكنك استخدام الطريقة القديمة-وتخزين list
بالكامل في المقام الأول مع <لأ href = "https://boltons.readthedocs.io/en/latest /iterutils.html#boltons.iterutils.chunked "يختلط =" noreferrer "> iterutils.chunked
.
فيما يلي قائمة بالطرق الإضافية:
منح
import itertools as it
import collections as ct
import more_itertools as mit
iterable = range(11)
n = 3
شفرة
المكتبة القياسية
list(it.zip_longest(*[iter(iterable)] * n))
# [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, None)]
d = {}
for i, x in enumerate(iterable):
d.setdefault(i//n, []).append(x)
list(d.values())
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
dd = ct.defaultdict(list)
for i, x in enumerate(iterable):
dd[i//n].append(x)
list(dd.values())
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
list(mit.chunked(iterable, n))
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
list(mit.sliced(iterable, n))
# [range(0, 3), range(3, 6), range(6, 9), range(9, 11)]
list(mit.grouper(n, iterable))
# [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, None)]
list(mit.windowed(iterable, len(iterable)//n, step=n))
# [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, None)]
مراجع
zip_longest
(منشور له صلة, منشور له صلة)setdefault
(النتائج المطلوبة تتطلب Python 3.6+)collections.defaultdict
(النتائج المطلوبة تتطلب Python 3.6+)more_itertools.chunked
(نشرت ذات الصلة)more_itertools.sliced
more_itertools.grouper
(منشور له صلة)more_itertools.windowed
(أنظر أيضاstagger
,zip_offset
)
+ مكتبة خارجية تقوم بتنفيذ وصفات itertools و اكثر. > pip install more_itertools