Permutations between two lists of unequal length
Solution 1
Note: This answer is for the specific question asked above. If you are here from Google and just looking for a way to get a Cartesian product in Python, itertools.product
or a simple list comprehension may be what you are looking for - see the other answers.
Suppose len(list1) >= len(list2)
. Then what you appear to want is to take all permutations of length len(list2)
from list1
and match them with items from list2. In python:
import itertools
list1=['a','b','c']
list2=[1,2]
[list(zip(x,list2)) for x in itertools.permutations(list1,len(list2))]
Returns
[[('a', 1), ('b', 2)], [('a', 1), ('c', 2)], [('b', 1), ('a', 2)], [('b', 1), ('c', 2)], [('c', 1), ('a', 2)], [('c', 1), ('b', 2)]]
Solution 2
The simplest way is to use itertools.product
:
a = ["foo", "melon"]
b = [True, False]
c = list(itertools.product(a, b))
>> [("foo", True), ("foo", False), ("melon", True), ("melon", False)]
Solution 3
May be simpler than the simplest one above:
>>> a = ["foo", "bar"]
>>> b = [1, 2, 3]
>>> [(x,y) for x in a for y in b] # for a list
[('foo', 1), ('foo', 2), ('foo', 3), ('bar', 1), ('bar', 2), ('bar', 3)]
>>> ((x,y) for x in a for y in b) # for a generator if you worry about memory or time complexity.
<generator object <genexpr> at 0x1048de850>
without any import
Solution 4
I was looking for a list multiplied by itself with only unique combinations, which is provided as this function.
import itertools
itertools.combinations(list, n_times)
Here as an excerpt from the Python docs on itertools
That might help you find what your looking for.
Combinatoric generators:
Iterator | Results
-----------------------------------------+----------------------------------------
product(p, q, ... [repeat=1]) | cartesian product, equivalent to a
| nested for-loop
-----------------------------------------+----------------------------------------
permutations(p[, r]) | r-length tuples, all possible
| orderings, no repeated elements
-----------------------------------------+----------------------------------------
combinations(p, r) | r-length tuples, in sorted order, no
| repeated elements
-----------------------------------------+----------------------------------------
combinations_with_replacement(p, r) | r-length tuples, in sorted order,
| with repeated elements
-----------------------------------------+----------------------------------------
product('ABCD', repeat=2) | AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD
permutations('ABCD', 2) | AB AC AD BA BC BD CA CB CD DA DB DC
combinations('ABCD', 2) | AB AC AD BC BD CD
combinations_with_replacement('ABCD', 2) | AA AB AC AD BB BC BD CC CD DD
Solution 5
the best way to find out all the combinations for large number of lists is:
import itertools
from pprint import pprint
inputdata = [
['a', 'b', 'c'],
['d'],
['e', 'f'],
]
result = list(itertools.product(*inputdata))
pprint(result)
the result will be:
[('a', 'd', 'e'),
('a', 'd', 'f'),
('b', 'd', 'e'),
('b', 'd', 'f'),
('c', 'd', 'e'),
('c', 'd', 'f')]
Related videos on Youtube
user1735075
Updated on February 24, 2021Comments
-
user1735075 about 3 years
I’m having trouble wrapping my head around a algorithm I’m try to implement. I have two lists and want to take particular combinations from the two lists.
Here’s an example.
names = ['a', 'b'] numbers = [1, 2]
the output in this case would be:
[('a', 1), ('b', 2)] [('b', 1), ('a', 2)]
I might have more names than numbers, i.e.
len(names) >= len(numbers)
. Here's an example with 3 names and 2 numbers:names = ['a', 'b', 'c'] numbers = [1, 2]
output:
[('a', 1), ('b', 2)] [('b', 1), ('a', 2)] [('a', 1), ('c', 2)] [('c', 1), ('a', 2)] [('b', 1), ('c', 2)] [('c', 1), ('b', 2)]
-
dm03514 over 11 years
-
user1735075 over 11 years@dm03514 I saw that, and found examples for somewhat similar goals using itertools but I'm prototyping in python but will write the final code in another language so I do not want to use any tools that are not avail elseway.
-
interjay over 11 yearsWhat you are asking for doesn't really make sense. If the first list contains A,B,C and the second contains 1,2, what result would you expect? It could be done if the example you gave had 4 different results of one letter and one number each (A1, A2, B1, B2), or if both lists had to have the same size.
-
Bakuriu over 11 yearsI agree with interjay. Please specify the result in the non-equal size case, otherwise it's not possible to provide a general solution.
-
user1735075 over 11 yearsHi Everyone, I updated the answer to show the output with 3 names and 2 numbers..I thought I explained it well, not sure why the downvote.
-
sloth over 11 yearsHow would the output look like for
name = 'a', 'b', 'c'
andnumber = 1, 2, 3
? -
Bakuriu over 11 yearsIs the order really important or is it enough to generate all of the "combinations" you want? Also
A1 B2 == B2 A1
? -
user1735075 over 11 years@Mr.Steak it would look like the example I had above with 2 names and 2 numbers but instead of 4 results there would be more because there are 3 items in the number list. bakuriu The order does not really matter, trying to capture the combinations.
-
ShadowRanger about 5 yearsNote for future folks dup-ing questions to this one: There is a decent chance that Get the cartesian product of a series of lists? is a better duplicate target (lots of stuff that should use
product
is being duplicated here, even though this question is not properly solved that way). In rarer cases, All possible replacements of two lists? may be better (when selecting a value from one of two lists at each index, which is aproduct
solution again, with azip
prepass). -
wim over 3 years@ShadowRanger Just made the same mistake myself. I've now made an edit to remove fluff and misdirections from the question.
-
-
user1735075 over 11 yearsThe result is exactly what I want, but is it possible to share the logic behind how to do it? If I convert my code to C or Java, I won't have access to zip or itertools(although they make life very very easy)
-
sloth over 11 years@user1735075 Have a look at the documentation
-
Bakuriu over 11 years@user1735075: do you know that python is open source? So you may simply download the sources and see what do they do. +1 to Mr. Steak for pointing out that the documentation actually has a sample implementation that does not use
zip
and similar. -
user1735075 over 11 yearsawesome..they document their algorithm. very helpful thank you interjay and mr. steak!
-
interjay almost 7 yearsOP wasn't asking for a Cartesian product, and this answer (as well as most of the others) doesn't give the expected result specified in the question.
-
xpy almost 7 years@interjay you are very right but as too many people seem to find this answer as correct then I can only assume that the title of the question is lacking context.
-
interjay almost 7 years@xpy The title is too short to explain everything. That's why you need to read the actual question.
-
Philipp Schwarz about 6 yearsBest solution! Thank you! Other solutions are either plain wrong or only work in specific cases like a > b etc.
-
Dalker almost 6 yearsMost Pythonic solution! (and avoids unnecessary imports)
-
m1nkeh almost 6 yearsi literally cannot get this to work, even with your example... all i get is a list of zip object.. :|
-
Josh Friedlander over 5 yearsOP wanted permuations, but Google sends anyone looking for combinations (like me) to this answer - glad to see it's got 8 times the votes!
-
Deepak Sharma over 5 yearsTime complexity is O(n^2)
-
Sabyasachi about 5 yearsBets solution!! Bare basics is the best way always
-
Bernhard Wagner almost 5 years@logic provides what should be the accepted solution.
-
toinbis over 4 yearsThanks, great answer!
-
Mattwmaster58 about 2 yearsSure, the time complexity is n^2, but surely this is completely unavoidable?