9

I have the following lists as an example:

a = ['#12908069', '#12906115', '#12904949', '#12904654', '#12904288', '#12903553']    
b = ['85028,', '83646,', '77015,', '90011,', '91902,', '80203,']    
c = ['9.09', '9.09', '1.81', '3.62', '1.81', '1.81', '9.09', '9.09', '1.81', '3.62', '1.81', '1.81']    
d = ['Zone 3', 'Zone 3', 'Zone 2']

What I'd like to achieve as an output, the first item set zipped as an example:

[('#12908069', '85028', (9.09, 9.09), 'Zone 3'), ...]

How do I get zip() to add an extra item for each tuple from list c?

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
Kenny Powers
  • 1,254
  • 2
  • 15
  • 25

4 Answers4

13

you can use list slices with a step of 2, see Explain Python's slice notation:

list(zip(a,b,zip(c[0::2],c[1::2]),d))
Community
  • 1
  • 1
Jacques Supcik
  • 619
  • 3
  • 8
6

using an idiom for clustering a data series into n-length groups from the zip documentation:

>>> gr = [iter(c)]*2
>>> list(zip(a, b, zip(*gr), d))
[('#12908069', '85028,', ('9.09', '9.09'), 'Zone 3'),
 ('#12906115', '83646,', ('1.81', '3.62'), 'Zone 3'),
 ('#12904949', '77015,', ('1.81', '1.81'), 'Zone 2')]

essentially, in order to get two consecutive elements from list c we put the same iterator on it in the gr list, which is made of two elements.

Then we pass those same iterators to zip (unpacking the list, as if we had passed the two iterators as two separate arguments to it).

That has the effect of collecting each two consecutive elements from list c.

We then pass such zip and the other lists to zip again to scan and pair the whole lot.

Pynchia
  • 10,996
  • 5
  • 34
  • 43
  • this is clever, but very un-maintainable IMO, I had to wrap my head around 2 copies of a reference to the same iterator – Aprillion Feb 06 '16 at 23:24
  • 1
    @Aprillion such idiom is quite common for clustering a data series into n-length groups – Pynchia Feb 06 '16 at 23:28
  • hmm, looks like it's been added to the documentation - https://bugs.python.org/issue23695 - I will just have to get used to it :) – Aprillion Feb 06 '16 at 23:34
  • 1
    @Aprillion BTW, note how it does not create any new list (at least in python 3), whereas slicing does. – Pynchia Feb 06 '16 at 23:42
3

Using one of the recipes from itertools:

>>> from itertools import zip_longest
>>> 
>>> def grouper(iterable, n, fillvalue=None):
...     "Collect data into fixed-length chunks or blocks"
...     # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
...     args = [iter(iterable)] * n
...     return zip_longest(*args, fillvalue=fillvalue)
... 
>>> list(zip(a, b, grouper(c, 2), d))
[('#12908069', '85028,', ('9.09', '9.09'), 'Zone 3'), ('#12906115', '83646,', ('1.81', '3.62'), 'Zone 3'), ('#12904949', '77015,', ('1.81', '1.81'), 'Zone 2')]
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
0

Try the following code:

a = ['#12908069', '#12906115', '#12904949', '#12904654', '#12904288', '#12903553']
b = ['85028,', '83646,', '77015,', '90011,', '91902,', '80203,']
c = ['9.09', '9.09', '1.81', '3.62', '1.81', '1.81', '9.09', '9.09', '1.81', '3.62', '1.81', '1.81']
d = ['Zone 3', 'Zone 3', 'Zone 2']

result = list(zip(a, b, [(c[i*2],c[i*2+1]) for i in range(len(c)//2)], d))
print(result)
Ren
  • 2,852
  • 2
  • 23
  • 45