我有一个Python脚本,它把一个整数列表作为输入,我需要一次处理四个整数。不幸的是,我无法控制输入,否则我将它作为一个四元素元组列表传入。目前,我以这种方式迭代它:
for i in range(0, len(ints), 4):
# dummy op for example code
foo += ints[i] * ints[i + 1] + ints[i + 2] * ints[i + 3]
不过,它看起来很像“C-think”,这让我怀疑有一种更python的方式来处理这种情况。该列表在迭代后被丢弃,因此不需要保留。也许这样会更好?
while ints:
foo += ints[0] * ints[1] + ints[2] * ints[3]
ints[0:4] = []
不过,感觉还是不太对。: - /
相关问题:在Python中如何将列表分割成大小均匀的块?
首先,我将它设计为将字符串拆分为子字符串以解析包含十六进制的字符串。
今天我把它变成复杂的,但仍然简单的生成器。
def chunker(iterable, size, reductor, condition):
it = iter(iterable)
def chunk_generator():
return (next(it) for _ in range(size))
chunk = reductor(chunk_generator())
while condition(chunk):
yield chunk
chunk = reductor(chunk_generator())
参数:
明显的
Iterable是任何包含/生成/迭代输入数据的Iterable /迭代器/生成器,
当然,大小是你想要得到的块的大小,
更有趣的
reductor is a callable, which receives generator iterating over content of chunk.
I'd expect it to return sequence or string, but I don't demand that.
You can pass as this argument for example list, tuple, set, frozenset,
or anything fancier. I'd pass this function, returning string
(provided that iterable contains / generates / iterates over strings):
def concatenate(iterable):
return ''.join(iterable)
Note that reductor can cause closing generator by raising exception.
condition is a callable which receives anything what reductor returned.
It decides to approve & yield it (by returning anything evaluating to True),
or to decline it & finish generator's work (by returning anything other or raising exception).
When number of elements in iterable is not divisible by size, when it gets exhausted, reductor will receive generator generating less elements than size.
Let's call these elements lasts elements.
I invited two functions to pass as this argument:
lambda x:x - the lasts elements will be yielded.
lambda x: len(x)==<size> - the lasts elements will be rejected.
replace <size> using number equal to size
def group_by(iterable, size):
"""Group an iterable into lists that don't exceed the size given.
>>> group_by([1,2,3,4,5], 2)
[[1, 2], [3, 4], [5]]
"""
sublist = []
for index, item in enumerate(iterable):
if index > 0 and index % size == 0:
yield sublist
sublist = []
sublist.append(item)
if sublist:
yield sublist
修改自Python的itertools文档中的Recipes部分:
from itertools import zip_longest
def grouper(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
例子
grouper('ABCDEFG', 3, 'x') # --> 'ABC' 'DEF' 'Gxx'
注意:在Python 2上使用izip_longest而不是zip_longest。
首先,我将它设计为将字符串拆分为子字符串以解析包含十六进制的字符串。
今天我把它变成复杂的,但仍然简单的生成器。
def chunker(iterable, size, reductor, condition):
it = iter(iterable)
def chunk_generator():
return (next(it) for _ in range(size))
chunk = reductor(chunk_generator())
while condition(chunk):
yield chunk
chunk = reductor(chunk_generator())
参数:
明显的
Iterable是任何包含/生成/迭代输入数据的Iterable /迭代器/生成器,
当然,大小是你想要得到的块的大小,
更有趣的
reductor is a callable, which receives generator iterating over content of chunk.
I'd expect it to return sequence or string, but I don't demand that.
You can pass as this argument for example list, tuple, set, frozenset,
or anything fancier. I'd pass this function, returning string
(provided that iterable contains / generates / iterates over strings):
def concatenate(iterable):
return ''.join(iterable)
Note that reductor can cause closing generator by raising exception.
condition is a callable which receives anything what reductor returned.
It decides to approve & yield it (by returning anything evaluating to True),
or to decline it & finish generator's work (by returning anything other or raising exception).
When number of elements in iterable is not divisible by size, when it gets exhausted, reductor will receive generator generating less elements than size.
Let's call these elements lasts elements.
I invited two functions to pass as this argument:
lambda x:x - the lasts elements will be yielded.
lambda x: len(x)==<size> - the lasts elements will be rejected.
replace <size> using number equal to size
另一种方法是使用双参数形式的iter:
from itertools import islice
def group(it, size):
it = iter(it)
return iter(lambda: tuple(islice(it, size)), ())
这可以很容易地适应使用填充(这类似于Markus Jarderot的答案):
from itertools import islice, chain, repeat
def group_pad(it, size, pad=None):
it = chain(iter(it), repeat(pad))
return iter(lambda: tuple(islice(it, size)), (pad,) * size)
这些甚至可以组合为可选的填充:
_no_pad = object()
def group(it, size, pad=_no_pad):
if pad == _no_pad:
it = iter(it)
sentinel = ()
else:
it = chain(iter(it), repeat(pad))
sentinel = (pad,) * size
return iter(lambda: tuple(islice(it, size)), sentinel)