1

Let say I have a nested list of string

lst = [['a'], ['b', 'c'], ['d', ['e', 'f']]]

I want to generate all possible combination from the nested list to something like this:

new_lst = [['a', 'b', 'd'],
           ['a', 'b', 'e', 'f'],
           ['a', 'c', 'd'],
           ['a', 'c', 'e', 'f']]

I have found some question that may related to my question. how to produce a nested list from two lists in python However, my question is more complicated issue.

cdlane
  • 40,441
  • 5
  • 32
  • 81
boated_tw
  • 414
  • 1
  • 9
  • 19
  • 1
    I would flatten the list and then use sets. `itertools` probably has a method that does this automatically. – Luke McPuke Jan 30 '18 at 06:20
  • possible duplicate of https://stackoverflow.com/questions/8371887/making-all-possible-combinations-of-a-list-in-python – Midhun Mohan Jan 30 '18 at 06:22
  • @MidhunMohan in that question they are taking combinations from a simple list while OP is asking product of his particular nested list – Vikas Periyadath Jan 30 '18 at 06:25
  • @JonKiparsky, I don't believe you *fixed* the title but diluted it. I believe the correct title would be more like, "How to apply itertools.product to a nested list in Python". – cdlane Jan 30 '18 at 07:03

5 Answers5

5

Here's what will do the trick -

import itertools
lst = [['a'], ['b', 'c'], ['d', ['e', 'f']]]
outp = list(itertools.product(*lst))
out = []
for i in outp:
    temp = []
    for j in i:
        if isinstance(j, list):
            for k in j:
                temp.append(k)
        else:
            temp.append(j)
    out.append(temp)
print(out)

Start off by forming the output materials using itertools.product and then simply formatting it in a way that the nested lists are flattened out.

Output

[['a', 'b', 'd'], ['a', 'b', 'e', 'f'], ['a', 'c', 'd'], ['a', 'c', 'e', 'f']]
Vivek Kalyanarangan
  • 8,951
  • 1
  • 23
  • 42
3

Similar to @VivekKalyanarangan but with a proper flattener:

>>> def flatten(nl):
...     for e in nl:
...         if isinstance(e, str):
...             yield e
...             continue
...         try:
...             yield from flatten(e)
...         except TypeError:
...             yield e
... 

>>> lst = [['a'], ['b', 'c'], ['d', ['e', 'f']]]
>>> 
>>> list(map(list, map(flatten, itertools.product(*lst))))
[['a', 'b', 'd'], ['a', 'b', 'e', 'f'], ['a', 'c', 'd'], ['a', 'c', 'e', 'f']]
Paul Panzer
  • 51,835
  • 3
  • 54
  • 99
  • If I change the data to be `lst = [[1], [2, 3], [4, [5, 6]]]`, this solution still works. So what is the `isinstance(e, str)` really doing for you? – cdlane Jan 30 '18 at 07:21
1

You can use chain.from_iterable() to flattern results:

from itertools import product, chain

lst = [['a'], ['b', 'c'], ['d', ['e', 'f']]]

[list(chain.from_iterable(i)) for i in product(*lst)]
# [['a', 'b', 'd'], ['a', 'b', 'e', 'f'], ['a', 'c', 'd'], ['a', 'c', 'e', 'f']]
Mykola Zotko
  • 15,583
  • 3
  • 71
  • 73
-1

Another way by using list comprehension

>>> ls = [['a'], ['b', 'c'], ['d', ['e', 'f']]]
>>> res = ['']
>>> for elem in ls:
...     res = [list(j) + list(e) for j in res for e in elem]
... 
>>> res
[['a', 'b', 'd'], ['a', 'b', 'e', 'f'], ['a', 'c', 'd'], ['a', 'c', 'e', 'f']]
Shishir
  • 89
  • 3
-2

Is this what you're looking for?

from itertools import permutations
lst = [['a'], ['b', 'c'], ['d', ['e', 'f']]]
list(permutations(lst))

Otherwise, give this a try:

lst = ['a','b','c','d','e','f']
list(permutations(lst))   ##will return all possible combos
thomas.mac
  • 1,236
  • 3
  • 17
  • 37