-1

The tuple that length is equal to 6 is correct one while the tuples with shorter length are artefacts that should be joined to give length of 6.

For example:

I have a list of tuples as below:

foo = [(3, 1, 0, 1, 1, 1), (3, 1), (1, 1), (3, 1),  (3, 1, 0, 1), (1, 2), (3, 3, 3, 1, 2, 2)]

len(foo[0]) = 6
len(foo[1]) = 2
len(foo[2]) = 2
len(foo[3]) = 2
len(foo[4]) = 4
len(foo[5]) = 2
len(foo[6]) = 6 

So it means that I want to have a list with the following output:

foo_1 = [(3, 1, 0, 1, 1, 1), (3, 1, 1, 1, 3, 1), (3, 1, 0, 1, 1, 2), (3, 3, 3, 1, 2, 2)]

where:

foo_1[1] = foo[1] + foo[2] + foo[3], 
foo_1[2] = foo[4] + foo[5]

Basically, I need to iterate over list of tuples and compare the length of each with 6. Then if the length of tuple is not equal to six I have to join tuples till their length will be 6.

Roman Lents
  • 113
  • 1
  • 8

3 Answers3

4
import itertools
foo=[(3, 1, 0, 1, 1, 1), (3, 1), (1, 1), (3, 1),  (3, 1, 0, 1), (1, 2), (3, 3, 3, 1, 2, 2)]
foo1=[i for t in foo for i in t]
list(itertools.zip_longest(*[iter(foo1)]*6))

Output:

[(3, 1, 0, 1, 1, 1),
 (3, 1, 1, 1, 3, 1),
 (3, 1, 0, 1, 1, 2),
 (3, 3, 3, 1, 2, 2)]

Or just iterate over and use slice

[foo1[i:i+6] for i in range(0,len(foo1),6)]

foo1 is list of all elements..and after that we can use slicing or zip_longest from itertools to get the desired result.

itertools.zip_longest

Make an iterator that aggregates elements from each of the iterables. If the iterables are of uneven length, missing values are filled-in with fillvalue. Iteration continues until the longest iterable is exhausted. Roughly equivalent to:

If the total length is not in multiples of 6

foo=[(3, 1, 0, 1, 1, 1), (3, 1), (1, 1), (3, 1),  (3, 1, 0, 1), (1, 2), (3, 3, 3, 1, 2, 2),(1,)

I've added an extra (1,)

list(itertools.zip_longest(*[iter(foo1)]*6))
(1, None, None, None, None, None)]

If we need some fill value instead of None then

list(itertools.zip_longest(*[iter(foo1)]*6,fillvalue=2))
(1, 2, 2, 2, 2, 2)
Ajay
  • 5,267
  • 2
  • 23
  • 30
4

You can create a function that flatten's the list of tuples, and then use generators and zip to group them into proper number of length.

>>> def flatten(lst):
        for tup in lst:
            yield from tup

>>> list(zip(*[flatten(foo)]*6))
[(3, 1, 0, 1, 1, 1),
 (3, 1, 1, 1, 3, 1),
 (3, 1, 0, 1, 1, 2),
 (3, 3, 3, 1, 2, 2)]

You can find more about how zip(*[iter(iterable)]*n) works here.

Or you can use the itertools.chain.from_iterable function to accomplish the flattening part:

>>> flat = chain.from_iterable(foo)

>>> list(zip(*[flat]*6))
[(3, 1, 0, 1, 1, 1),
 (3, 1, 1, 1, 3, 1),
 (3, 1, 0, 1, 1, 2),
 (3, 3, 3, 1, 2, 2)]
Sayandip Dutta
  • 15,602
  • 4
  • 23
  • 52
2

An easy way to get the results could use more_itertools.chunked

from more_itertools import chunked
from itertools import chain

foo = [(3, 1, 0, 1, 1, 1), (3, 1), (1, 1), (3, 1),
       (3, 1, 0, 1), (1, 2), (3, 3, 3, 1, 2, 2)]

for chunk in chunked(chain.from_iterable(foo), 6):
    print(chunk)

Prints:

[3, 1, 0, 1, 1, 1]
[3, 1, 1, 1, 3, 1]
[3, 1, 0, 1, 1, 2]
[3, 3, 3, 1, 2, 2]
Chris Charley
  • 6,403
  • 2
  • 24
  • 26