I have a flat list of numbers that are logically in groups of 3, where each triple is (number, __ignored, flag[0 or 1]), eg:
[7,56,1, 8,0,0, 2,0,0, 6,1,1, 7,2,0, 2,99,1]
I would like to (pythonically) process this list to create a new list of numbers based on the value of 'flag': if 'flag' is 1, then I want 'number', else 0. So the above list would become:
[7, 0, 0, 6, 0, 2]
My initial attempt at doing this is:
list = [7,56,1, 8,0,0, 2,0,0, 6,1,1, 7,2,0, 2,99,1]
numbers = list[::3]
flags = list[2::3]
result = []
for i,number in enumerate(numbers):
result.append(number if flags[i] == 1 else 0)
This works, but it seems to me that there should be a better way to extract tuples cleanly from a list. Something like:
list = [7,56,1, 8,0,0, 2,0,0, 6,1,1, 7,2,0, 2,99,1]
for (number, __, flag) in list:
...etc
But I don't seem to be able to do this.
I could just loop through the entire list:
result = []
for i in range(0, len(list), 3):
result.append(list[i] if list[i+2] == 1 else 0)
Which seems smaller and more efficient.
I am unclear about the best option here. Any advice would be appreciated.
Note: I have accepted the answer by wim:
[L[i]*L[i+2] for i in range(0, len(L), 3)]
But want to reiterate that both wims and ShadowRangers responses work. I accepted wim's answer based on simplicity and clarity (and, to a lesser extent, compatibility with python 2, though ShadowRanger pointed out that zip was in Py2 as well, so this basis is invalid).
The answer by ShadowRanger:
[number if flag else 0 for number, _, flag in zip(*[iter(mylist)]*3)]
also does exactly what I thought I wanted (providing tuples), but is a little obscure and requires zip. As wim noted, ShadowRanger's answer would be very well suited to a stream of data rather than a fixed list.
I would also note that ShadowRanger's answer adds obscure use of zip() (which will become less obscure with time), but adds clarity by the use of named values for the tuple, so it's a bit of a win/lose.
For those struggling to understand zip(*[iter(mylist)]*3)], it creates three copies of the one iterator, which are then used to contruct tuples. Because it's the same iterator, each use advances the iterator, making the tuples exactly as I requested.
For both clarity and generality, I am also somewhat inclined to a modified version of the solution from @ShadowRanger:
i = iter(mylist)
[number if flag else 0 for number, _, flag in zip(i, i, i)]
(which, to me, seems much less obscure).