1

I have the following lists:

sectors = ["A", "B"]

rows = [['1', '2', '3'], ['1', '2', '3', '4']]

seats = [['ab', 'abcd', 'ab'], ['ab', 'abcd', 'ab', 'abcd']]

and I want to create products like A1a, A1b, A2a, A2b, A2c ...

this code

  combinations = []
  for i in range(len(rows)):
    c = list(zip_longest(repeat(sectors[i], len(rows[i])), rows[i], seats[i]))
    combinations += c

  for c in combinations:
    for x in product(*c):
       print("".join(x))

prints the desired results as A1a A1b A2a A2b A2c A2d A3a ...

Can this be solved in a better and more readable way, I am practicing itertools and it is a bit confusing for me.

3
  • You mean with separator? You can use print(", ".join(x)) to list be separated with comma and one whitespace. Commented Jan 20, 2022 at 22:25
  • No, is there a more efficient/readable way to create all possible combinations(products) of the list in the example? It was more natural for me to use nested for loops, and itertools with its methods scrambled my head. Or the above code is acceptable. Commented Jan 20, 2022 at 22:30
  • Can you explain in words what you are trying to do, and/or post your solution using for loops? Commented Jan 20, 2022 at 22:55

2 Answers 2

1

Not sure if that is what you want or if it is more elegant:

from itertools import chain, product

combinations = product(
    sectors,
    chain.from_iterable(chain.from_iterable(rows)),
    chain.from_iterable(chain.from_iterable(seats)),
)
joined_combinations = map(lambda t: "".join(t), combinations)
list(joined_combinations)
# returns
['A1a', 'A1b', 'A1a', 'A1b', 'A1c', 'A1d', 'A1a', ...]

Explanation: Applying two times chain.from_iterable you can "unpack" individual characters from the nested lists, then creating the product of the items of the unnested lists (which creates 3-tuples) and finally join the items of each 3-tuple together.
If you want to avoid duplicates you can put a set() around each argument in the product.

Sign up to request clarification or add additional context in comments.

1 Comment

This is nice, thanks for the explanation.
1

Since you're creating triples from 3 nested lists, not Cartesian product, I think it may be more intuitive to zip the corresponding sublists and use a loop.

out = [sector + row + s for sector, rws, sts in zip(sectors, rows, seats) 
       for row, seat in zip(rws, sts) for s in seat] 

If we want to use itertools.product, first repeat elements in sectors to match the lengths of sublists of the other lists and instead of creating the product elements manually like in the inner-most loop above, we iterate over the product itself. Of course, this is a lot like your own approach.

repsectors = [repeat(sector, len(rows[i])) for i, sector in enumerate(sectors)]
out = [''.join(x) for tpl1 in zip(repsectors, rows, seats) 
       for tpl2 in zip(*tpl1) for x in itertools.product(*tpl2)]

Output:

['A1a', 'A1b', 'A2a', 'A2b', 'A2c', 'A2d', 'A3a', 'A3b', 'B1a', 'B1b', 'B2a', 'B2b', 'B2c', 'B2d', 'B3a', 'B3b', 'B4a', 'B4b', 'B4c', 'B4d']

1 Comment

Smart, a somewhat difficult to read for me at this moment though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.