Питонический способ перебора последовательности, по 4 предмета за раз
Возможный дубликат:
Каков самый "питонический" способ перебора списка в кусках?
Я читаю некоторые 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 должен действительно сделать все рецепты в качестве стандартных функций...)
Вы можете использовать функцию 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 для этого.
Ответ 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
Ответ 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
Ответ 5
Попробуйте что-то вроде этого:
for red, green, blue, alpha in raw_png_data:
#do something
Вы можете вытащить несколько элементов и никогда не использовать итератор.:)
Изменить: это означало бы, что raw_png_data должен быть списком из 4 кортежей значений. Было бы очень pythonic поставить каждую группу rgba в кортеж, а затем добавить его в raw_png_data и прокрутить, как в моем примере.