2013-05-01 69 views
2

看完How do you split a list into evenly sized chunks?後,一直看到發生這種錯誤https://code.djangoproject.com/ticket/18972塊爲什麼不是python標準庫的一部分?

itertools爲什麼不是chunk函數?

編輯:從http://docs.python.org/2/library/itertools.html#recipes grouper不具有相同的行爲chunks

例子:

chunks([1, 2, 3, 4, 5], 3) 
# Should return [[1, 2, 3], [4, 5]] or the iterator equivalent. 
+0

因爲它的簡單和明顯不夠使用列表理解在一行來實現? – wim 2013-05-01 05:28:59

+0

@wim這聽起來像是我的另一個原因:) – razpeitia 2013-05-01 05:42:54

+2

滑動窗口迭代器將是我將添加到標準庫的另一個。 – 2013-05-01 06:10:41

回答

2

這不是在itertools,但它提到非常頁的itertools爲配方:

http://docs.python.org/2/library/itertools.html#recipes

def grouper(n, iterable, fillvalue=None): 
    "Collect data into fixed-length chunks or blocks" 
    # grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx 
    args = [iter(iterable)] * n 
    return izip_longest(fillvalue=fillvalue, *args) 

你可能會問爲什麼所有其他食譜不包括在itertools :)

+0

但它沒有相同的功能。 '塊'不會填補最後一塊的空白。 – razpeitia 2013-05-01 05:16:28

+0

@razpeitia如果你有fillvalue = None,會發生什麼? – Patashu 2013-05-01 05:17:15

+0

它填寫'無'女巫不是例外。 – razpeitia 2013-05-01 05:18:51

4

在這裏發佈這樣的問題不是像這樣的問題添加到Python的方式。你應該嘗試一個Python郵件列表。

我用你請求的語義爲你實現了chunks()。最後一塊的處理恰到好處是有點棘手,但否則這很容易。如果它被添加到itertools它將被寫入C,所以它會更快。

在Python 2.6,Python 2.7和Python 3.2中進行測試和工作。

import itertools as it 
import sys 

# use lazy xrange on 2.x; on 3.x plain "range" is always lazy 
if sys.version_info[0] < 3: 
    _range = xrange 
else: 
    _range = range 

def chunks(iterable, n): 
    """ 
    Yield up lists of n elements, taken from iterable. 
    If length of iterable is not evenly divisible by n, the last list will be short. 
    """ 
    if n < 1: 
     raise ValueError("n must be >= 1") 

    itr = iter(iterable) 
    try: 
     while True: 
      lst = [] 
      for _ in _range(n): 
       lst.append(next(itr)) 
      if not lst: 
       break 
      yield lst 
    except StopIteration: 
     # Only yield up a partial chunk if it is not zero length. 
     if lst: 
      yield lst 

print(list(chunks([1, 2, 3, 4, 5, 6], 3))) # prints: [[1, 2, 3], [4, 5, 6]] 
print(list(chunks([1, 2, 3, 4, 5], 3))) # prints: [[1, 2, 3], [4, 5]] 
print(list(chunks([], 3))) # prints: [] 
print(list(chunks([1, 2], 0))) # raises ValueError exception 

編輯:

上述解決方案的效率低下是有點纏着我。我很確定必須使用itertools.islice()更簡單的解決方案,所以我想通了。我更喜歡這個。

def chunks(iterable, n): 
    """ 
    Yield up lists of n elements, taken from iterable. 
    If length of iterable is not evenly divisible by n, the last list will be short. 
    """ 
    if n < 1: 
     raise ValueError("n must be >= 1") 

    itr = iter(iterable) 

    while True: 
     lst = list(it.islice(itr, n)) 
     if not lst: 
      break 
     yield lst 
+0

謝謝,先生!我非常感謝你的努力,我會嘗試一下郵件列表的東西。 – razpeitia 2013-05-01 06:11:15

相關問題