Python: Combination in lists of lists (?)
Asked Answered
P

3

5

First of all I wanted to say that my title is probably not describing my question correctly. I don't know how the process I am trying to accomplish is called, which made searching for a solution on stackoverflow or google very difficult. A hint regarding this could already help me a lot!

What I currently have are basically two lists with lists as elements. Example:

List1 = [ [a,b], [c,d,e], [f] ]
List2 = [ [g,h,i], [j], [k,l] ]

These lists are basically vertices of a graph I am trying to create later in my project, where the edges are supposed to be from List1 to List2 by rows.

If we look at the first row of each of the lists, I therefore have:

[a,b] -> [g,h,i]

However, I want to have assingments/edges of unique elements, so I need:

[a] -> [g]
[a] -> [h]
[a] -> [i]
[b] -> [g]
[b] -> [h]
[b] -> [i]

The result I want to have is another list, with these unique assigments as elements, i.e.

List3 = [ [a,g], [a,h], [a,i], [b,g], ...]

Is there any elegant way to get from List1 and List2 to List 3?

The way I wanted to accomplish that is by going row by row, determining the amount of elements of each row and then write clauses and loops to create a new list with all combinations possible. This, however, feels like a very inefficient way to do it.

Protohistory answered 18/5, 2015 at 12:18 Comment(3)
It looks like you want the itertools.product of each pair made by zipping (or itertools.izipping in 2.x) the two lists together.Tonsillectomy
@Tonsillectomy beat me to it, but I agree, this is a job for itertools ( docs.python.org/2/library/itertools.html )Beaverboard
Thank you for your comments, I think this is exactly what I was looking for! I am trying out the solution outlined by Cyber below now.Protohistory
E
13

You can zip your two lists, then use itertools.product to create each of your combinations. You can use itertools.chain.from_iterable to flatten the resulting list.

>>> import itertools
>>> List1 = [ ['a','b'], ['c','d','e'], ['f'] ]
>>> List2 = [ ['g','h','i'], ['j'], ['k','l'] ]
>>> list(itertools.chain.from_iterable(itertools.product(a,b) for a,b in zip(List1, List2)))
[('a', 'g'), ('a', 'h'), ('a', 'i'), ('b', 'g'), ('b', 'h'), ('b', 'i'), ('c', 'j'), ('d', 'j'), ('e', 'j'), ('f', 'k'), ('f', 'l')]
Eligible answered 18/5, 2015 at 12:24 Comment(4)
since you are using itertools, you may as well chainInbreeding
chain.from_iterable could be used to flatten the list. Of course you might need an extra list() call if a generator is not sufficient.Hurty
The user asked for list within a list not a tuple inside a list.So you could you both the example here @Cyber.And your answer was goodCandie
Thank you so much! I really have to get more familiar with these tools, instead of writing everything with for-loops.Protohistory
D
2

If you don't want to use itertools, you can also use list comprehensions in combination with zip to do this fairly elegantly:

lst1 = [['a','b'], ['c','d','e'], ['f']]
lst2 = [['g','h','i'], ['j'], ['k','l']]
edges = [[x, y] for il1, il2 in zip(lst1, lst2) for x in il1 for y in il2]
Dextrous answered 18/5, 2015 at 12:55 Comment(0)
D
0
import itertools
k = []
for a,b in zip(List1,List2):
    for j in itertools.product(a,b):
        k.append(j)
print k
Durrell answered 18/5, 2015 at 12:50 Comment(1)
Some what similar to the above solution without using itertools.chain()Durrell

© 2022 - 2024 — McMap. All rights reserved.