2013-05-01 72 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

相关问题