Pythonic方式迭代序列,一次4个项目[重复]
Posted
技术标签:
【中文标题】Pythonic方式迭代序列,一次4个项目[重复]【英文标题】:Pythonic way to iterate over sequence, 4 items at a time [duplicate] 【发布时间】:2011-03-25 19:27:55 【问题描述】:可能重复:What is the most “pythonic” way to iterate over a list in chunks?
我正在读取一些 PNG 数据,每个像素有 4 个通道。我想一次迭代 1 个像素的数据(意味着每 4 个元素 = 1 个像素,rgba)。
red_channel = 0
while red_channel < len(raw_png_data):
green_channel, blue_channel, alpha_channel = red_channel +1, red_channel +2, red_channel +3
# do something with my 4 channels of pixel data ... raw_png_data[red_channel] etc
red_channel += 4
这种方式看起来并不“正确”。有没有更 Pythonic 的方式来迭代一个序列,一次 4 个项目,然后将这 4 个项目解包?
【问题讨论】:
【参考方案1】:(Python 的 itertools 确实应该将 all recipes 设为标准函数...)
你可以使用grouper
函数:
from itertools import zip_longest
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
然后你可以迭代像素
for r,g,b,a in grouper(4, raw_png_data):
....
或者,您可以使用
irpd = iter(raw_png_data)
for r,g,b,a in zip(irpd, irpd, irpd, irpd): # use itertools.izip in Python 2.x
....
请注意,如果可迭代的长度不是 4 的倍数,这将截断最后几个字节。OTOH,grouper
函数使用izip_longest
,因此额外的字节将用 None 填充。
【讨论】:
【参考方案2】:vars = [1, 2, 3, 4, 5, 6, 7, 8]
for a, b, c, d in zip(*[iter(vars)]*4):
print a, b, c, d
【讨论】:
但请注意。此解决方案仅适用于 vars 列表长度等分到 4,迭代 4 这对我有用,但正如@EugeneNagorny 所说,任何使用它的人都应该注意,如果您的列表中的项目少于“等分”的倍数,它将省略“余数”。例如,对于列表中的 10 个值和 4 个等分试样,它只会发出两组四个值,忽略最后两个。【参考方案3】:from itertools import izip
for r,g,b,a in izip(*[iter(data)]*4):
...
【讨论】:
【参考方案4】:for r, g, b, t in (data[i:i+4] for i in xrange(0, len(data)/4*4, 4)):
print r, g, b, t
【讨论】:
并非所有序列都支持索引。data
很可能是一个生成器。【参考方案5】:
试试这样的:
for red, green, blue, alpha in raw_png_data:
#do something
您可以提取多个项目,而不必使用迭代器。 :)
编辑:这意味着 raw_png_data 需要是 4 个值元组的列表。将每个 rgba 组放入一个元组中,然后将其附加到 raw_png_data 并像我的示例一样遍历它是最 Pythonic 的。
【讨论】:
显然这不起作用,除非 raw_png_data 是一个元组列表。对吗? 是的,但最好在创建 raw_png_data 时将它们分组为元组,因为每组 4 个值都是相关的。 @excid3 这就是这个问题要问的,如何将原始序列分组为元组。以上是关于Pythonic方式迭代序列,一次4个项目[重复]的主要内容,如果未能解决你的问题,请参考以下文章