Pythonic way to iterate over sequence, 4 items at a time [duplicate]

Possible Duplicate:
What is the most “pythonic” way to iterate over a list in chunks?

I am reading in some PNG data, which has 4 channels per pixel. I would like to iterate over the data 1 pixel at a time (meaning every 4 elements = 1 pixel, 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

This way doesnt really seem "right". Is there a more Pythonic way to iterate over a sequence, 4 items at a time, and have those 4 items unpacked?

31
задан Community 23 May 2017 в 12:17
поделиться

5 ответов

(itertools Python действительно должны делать все рецепты как стандартные функции ...)

Вы можете использовать функцию grouper :

from itertools import izip_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.

33
ответ дан 27 November 2019 в 22:02
поделиться
vars = [1, 2, 3, 4, 5, 6, 7, 8]
for a, b, c, d in zip(*[iter(vars)]*4):
    print a, b, c, d
25
ответ дан 27 November 2019 в 22:02
поделиться
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
3
ответ дан 27 November 2019 в 22:02
поделиться
from itertools import izip
for r,g,b,a in izip(*[iter(data)]*4):
    ...
6
ответ дан 27 November 2019 в 22:02
поделиться

Попробуйте что-нибудь вроде этого:

for red, green, blue, alpha in raw_png_data:
    #do something

Вы можете вытащить несколько элементов и никогда не использовать итератор. :)

Edit: Это означает, что raw_png_data должен быть списком из 4 кортежей значений. Наиболее питонично было бы поместить каждую группу rgba в кортеж, а затем добавить его к raw_png_data и выполнить итерацию, как в моем примере.

-2
ответ дан 27 November 2019 в 22:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: