Get the cartesian product of a series of lists?
How can I get the Cartesian product (every possible combination of values) from a group of lists?
Input:
somelists = [
[1, 2, 3],
['a', 'b'],
[4, 5]
]
Desired output:
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), (2, 'a', 5) ...]
python list
add a comment |
How can I get the Cartesian product (every possible combination of values) from a group of lists?
Input:
somelists = [
[1, 2, 3],
['a', 'b'],
[4, 5]
]
Desired output:
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), (2, 'a', 5) ...]
python list
15
be aware that 'every possible combination' is not quite the same as 'Cartesian product', since in Cartesian products, duplicates are allowed.
– Triptych
Feb 10 '09 at 20:08
6
Is there a non duplicate version of cartesian product?
– KJW
Nov 13 '13 at 5:32
9
@KJW Yes,set(cartesian product)
– NoBugs
Feb 12 '15 at 7:04
4
There should be no duplicates in a Cartesian product, unless the input lists contain duplicates themselves. If you want no duplicates in the Cartesian product, useset(inputlist)
over all your input lists. Not on the result.
– CamilB
Aug 24 '17 at 8:39
add a comment |
How can I get the Cartesian product (every possible combination of values) from a group of lists?
Input:
somelists = [
[1, 2, 3],
['a', 'b'],
[4, 5]
]
Desired output:
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), (2, 'a', 5) ...]
python list
How can I get the Cartesian product (every possible combination of values) from a group of lists?
Input:
somelists = [
[1, 2, 3],
['a', 'b'],
[4, 5]
]
Desired output:
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), (2, 'a', 5) ...]
python list
python list
edited Jan 19 '17 at 2:31
martineau
67.6k1089182
67.6k1089182
asked Feb 10 '09 at 19:54
ʞɔıuʞɔıu
29.5k2683125
29.5k2683125
15
be aware that 'every possible combination' is not quite the same as 'Cartesian product', since in Cartesian products, duplicates are allowed.
– Triptych
Feb 10 '09 at 20:08
6
Is there a non duplicate version of cartesian product?
– KJW
Nov 13 '13 at 5:32
9
@KJW Yes,set(cartesian product)
– NoBugs
Feb 12 '15 at 7:04
4
There should be no duplicates in a Cartesian product, unless the input lists contain duplicates themselves. If you want no duplicates in the Cartesian product, useset(inputlist)
over all your input lists. Not on the result.
– CamilB
Aug 24 '17 at 8:39
add a comment |
15
be aware that 'every possible combination' is not quite the same as 'Cartesian product', since in Cartesian products, duplicates are allowed.
– Triptych
Feb 10 '09 at 20:08
6
Is there a non duplicate version of cartesian product?
– KJW
Nov 13 '13 at 5:32
9
@KJW Yes,set(cartesian product)
– NoBugs
Feb 12 '15 at 7:04
4
There should be no duplicates in a Cartesian product, unless the input lists contain duplicates themselves. If you want no duplicates in the Cartesian product, useset(inputlist)
over all your input lists. Not on the result.
– CamilB
Aug 24 '17 at 8:39
15
15
be aware that 'every possible combination' is not quite the same as 'Cartesian product', since in Cartesian products, duplicates are allowed.
– Triptych
Feb 10 '09 at 20:08
be aware that 'every possible combination' is not quite the same as 'Cartesian product', since in Cartesian products, duplicates are allowed.
– Triptych
Feb 10 '09 at 20:08
6
6
Is there a non duplicate version of cartesian product?
– KJW
Nov 13 '13 at 5:32
Is there a non duplicate version of cartesian product?
– KJW
Nov 13 '13 at 5:32
9
9
@KJW Yes,
set(cartesian product)
– NoBugs
Feb 12 '15 at 7:04
@KJW Yes,
set(cartesian product)
– NoBugs
Feb 12 '15 at 7:04
4
4
There should be no duplicates in a Cartesian product, unless the input lists contain duplicates themselves. If you want no duplicates in the Cartesian product, use
set(inputlist)
over all your input lists. Not on the result.– CamilB
Aug 24 '17 at 8:39
There should be no duplicates in a Cartesian product, unless the input lists contain duplicates themselves. If you want no duplicates in the Cartesian product, use
set(inputlist)
over all your input lists. Not on the result.– CamilB
Aug 24 '17 at 8:39
add a comment |
11 Answers
11
active
oldest
votes
In Python 2.6+
import itertools
for element in itertools.product(*somelists):
print(element)
Documentation:
Python 3 - itertools.product
19
Just wanted to add the '*' character is required if you use the variable somelists as provided by the OP.
– brian buck
Jan 13 '11 at 22:51
1
@jaska:product()
generatesnitems_in_a_list ** nlists
elements in the result (reduce(mul, map(len, somelists))
). There is no reason to believe that yielding a single element is notO(nlists)
(amortized) i.e., the time complexity is the same as for simple nestedfor
-loops e.g., for the input in the question:nlists=3
, total number of elements in the result:3*2*2
, and each element hasnlists
items (3
in this case).
– jfs
Aug 14 '15 at 22:08
2
What is the use of*
before somelists? What does it do?
– Vineet Kumar Doshi
Aug 25 '15 at 9:04
6
@VineetKumarDoshi: Here it is used to unpcak a list into multiple arguments to the function call. Read more here: stackoverflow.com/questions/36901/…
– Moberg
Sep 15 '15 at 6:20
3
Note: This works only if each list contains at least one item
– igo
Sep 13 '17 at 12:35
|
show 2 more comments
import itertools
>>> for i in itertools.product([1,2,3],['a','b'],[4,5]):
... print i
...
(1, 'a', 4)
(1, 'a', 5)
(1, 'b', 4)
(1, 'b', 5)
(2, 'a', 4)
(2, 'a', 5)
(2, 'b', 4)
(2, 'b', 5)
(3, 'a', 4)
(3, 'a', 5)
(3, 'b', 4)
(3, 'b', 5)
>>>
add a comment |
For Python 2.5 and older:
>>> [(a, b, c) for a in [1,2,3] for b in ['a','b'] for c in [4,5]]
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4),
(2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5),
(3, 'b', 4), (3, 'b', 5)]
Here's a recursive version of product()
(just an illustration):
def product(*args):
if not args:
return iter(((),)) # yield tuple()
return (items + (item,)
for items in product(*args[:-1]) for item in args[-1])
Example:
>>> list(product([1,2,3], ['a','b'], [4,5]))
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4),
(2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5),
(3, 'b', 4), (3, 'b', 5)]
>>> list(product([1,2,3]))
[(1,), (2,), (3,)]
>>> list(product())
>>> list(product())
[()]
The recursive version doesn't work if some ofargs
are iterators.
– jfs
Feb 10 '09 at 21:43
add a comment |
with itertools.product:
import itertools
result = list(itertools.product(*somelists))
5
What is the use of*
before somelists?
– Vineet Kumar Doshi
Aug 25 '15 at 9:04
@VineetKumarDoshi "product(somelists)" is a cartesian product between the sublists in a way that Python first get "[1, 2, 3]" as an element and then gets other element after next comman and that is linebreak so the first product term is ([1, 2, 3],), similary for the second ([4, 5],) and so "[([1, 2, 3],), ([4, 5],), ([6, 7],)]". If you wanna get a cartesian product between elements inside the tuples, you need to tell Python with Asterisk about the tuple structure. For dictionary, you use **. More here.
– hhh
Feb 15 '16 at 23:13
add a comment |
In Python 2.6 and above you can use 'itertools.product`. In older versions of Python you can use the following (almost -- see documentation) equivalent code from the documentation, at least as a starting point:
def product(*args, **kwds):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
pools = map(tuple, args) * kwds.get('repeat', 1)
result = []
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
The result of both is an iterator, so if you really need a list for furthert processing, use list(result)
.
Per the documentation, the actual itertools.product implementation does NOT build intermediate results, which could be expensive. Using this technique could get out of hand quite quickly for moderately sized lists.
– Triptych
Feb 10 '09 at 20:05
3
i can only point the OP to the documentation, not read it for him.
– user3850
Feb 10 '09 at 20:19
1
The code from the documentation is meant to demonstrate what the product function does, not as a workaround for earlier versions of Python.
– Triptych
Mar 10 '09 at 21:07
2
your point being?
– user3850
Mar 10 '09 at 22:37
add a comment |
I would use list comprehension :
somelists = [
[1, 2, 3],
['a', 'b'],
[4, 5]
]
cart_prod = [(a,b,c) for a in somelists[0] for b in somelists[1] for c in somelists[2]]
I really like this solution using list comprehensions. I don't know why isn't upvoted more, it's so simple.
– llekn
Nov 30 '16 at 17:38
9
@llekn because the code seems to be fixed to the number of lists
– Bằng Rikimaru
Jan 16 '17 at 15:33
add a comment |
Here is a recursive generator, which doesn't store any temporary lists
def product(ar_list):
if not ar_list:
yield ()
else:
for a in ar_list[0]:
for prod in product(ar_list[1:]):
yield (a,)+prod
print list(product([[1,2],[3,4],[5,6]]))
Output:
[(1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6)]
1
They're stored in the stack, though.
– Quentin Pradet
Mar 16 '15 at 11:09
@QuentinPradet do you mean a generator likedef f(): while True: yield 1
will keep on increasing its stack size as we go through it?
– Anurag Uniyal
Mar 16 '15 at 22:42
no, but def f(): yield 1; f() will, right?
– Quentin Pradet
Mar 17 '15 at 10:09
@QuentinPradet yeah, but even in this case only the stack needed for max depth, not the whole list, so in this case stack of 3
– Anurag Uniyal
Mar 17 '15 at 16:14
It's true, sorry. A benchmark could be interesting. :)
– Quentin Pradet
Mar 17 '15 at 18:24
add a comment |
Although there are many answers already, I would like to share some of my thoughts:
Iterative approach
def cartesian_iterative(pools):
result = []
for pool in pools:
result = [x+[y] for x in result for y in pool]
return result
Recursive Approach
def cartesian_recursive(pools):
if len(pools) > 2:
pools[0] = product(pools[0], pools[1])
del pools[1]
return cartesian_recursive(pools)
else:
pools[0] = product(pools[0], pools[1])
del pools[1]
return pools
def product(x, y):
return [xx + [yy] if isinstance(xx, list) else [xx] + [yy] for xx in x for yy in y]
Lambda Approach
def cartesian_reduct(pools):
return reduce(lambda x,y: product(x,y) , pools)
In "Iterative Approach", why is result declared as result = [] I know that it is list_of_list but in general even if we have declare list_of_list we use and not []
– Sachin S
Jul 16 '17 at 15:44
I'm a bit of a newby in terms of Pythonic solutions. Would you or some passerby please write the list comprehension in the "iterative approach" in separate loops?
– Johnny Boy
Dec 10 '18 at 17:03
add a comment |
Just to add a bit to what has already been said: if you use sympy, you can use symbols rather than strings which makes them mathematically useful.
import itertools
import sympy
x, y = sympy.symbols('x y')
somelist = [[x,y], [1,2,3], [4,5]]
somelist2 = [[1,2], [1,2,3], [4,5]]
for element in itertools.product(*somelist):
print element
About sympy.
add a comment |
A minor modification to the above recursive generator solution in variadic flavor:
def product_args(*args):
if args:
for a in args[0]:
for prod in product_args(*args[1:]) if args[1:] else ((),):
yield (a,) + prod
And of course a wrapper which makes it work exactly the same as that solution:
def product2(ar_list):
"""
>>> list(product(()))
[()]
>>> list(product2(()))
"""
return product_args(*ar_list)
with one trade-off: it checks if recursion should break upon each outer loop, and one gain: no yield upon empty call, e.g.product(())
, which I suppose would be semantically more correct (see the doctest).
Regarding list comprehension: the mathematical definition applies to an arbitrary number of arguments, while list comprehension could only deal with a known number of them.
add a comment |
Recursive Approach:
def rec_cart(start, array, partial, results):
if len(partial) == len(array):
results.append(partial)
return
for element in array[start]:
rec_cart(start+1, array, partial+[element], results)
rec_res =
some_lists = [[1, 2, 3], ['a', 'b'], [4, 5]]
rec_cart(0, some_lists, , rec_res)
print(rec_res)
Iterative Approach:
def itr_cart(array):
results = []
for i in range(len(array)):
temp =
for res in results:
for element in array[i]:
temp.append(res+[element])
results = temp
return results
some_lists = [[1, 2, 3], ['a', 'b'], [4, 5]]
itr_res = itr_cart(some_lists)
print(itr_res)
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f533905%2fget-the-cartesian-product-of-a-series-of-lists%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
11 Answers
11
active
oldest
votes
11 Answers
11
active
oldest
votes
active
oldest
votes
active
oldest
votes
In Python 2.6+
import itertools
for element in itertools.product(*somelists):
print(element)
Documentation:
Python 3 - itertools.product
19
Just wanted to add the '*' character is required if you use the variable somelists as provided by the OP.
– brian buck
Jan 13 '11 at 22:51
1
@jaska:product()
generatesnitems_in_a_list ** nlists
elements in the result (reduce(mul, map(len, somelists))
). There is no reason to believe that yielding a single element is notO(nlists)
(amortized) i.e., the time complexity is the same as for simple nestedfor
-loops e.g., for the input in the question:nlists=3
, total number of elements in the result:3*2*2
, and each element hasnlists
items (3
in this case).
– jfs
Aug 14 '15 at 22:08
2
What is the use of*
before somelists? What does it do?
– Vineet Kumar Doshi
Aug 25 '15 at 9:04
6
@VineetKumarDoshi: Here it is used to unpcak a list into multiple arguments to the function call. Read more here: stackoverflow.com/questions/36901/…
– Moberg
Sep 15 '15 at 6:20
3
Note: This works only if each list contains at least one item
– igo
Sep 13 '17 at 12:35
|
show 2 more comments
In Python 2.6+
import itertools
for element in itertools.product(*somelists):
print(element)
Documentation:
Python 3 - itertools.product
19
Just wanted to add the '*' character is required if you use the variable somelists as provided by the OP.
– brian buck
Jan 13 '11 at 22:51
1
@jaska:product()
generatesnitems_in_a_list ** nlists
elements in the result (reduce(mul, map(len, somelists))
). There is no reason to believe that yielding a single element is notO(nlists)
(amortized) i.e., the time complexity is the same as for simple nestedfor
-loops e.g., for the input in the question:nlists=3
, total number of elements in the result:3*2*2
, and each element hasnlists
items (3
in this case).
– jfs
Aug 14 '15 at 22:08
2
What is the use of*
before somelists? What does it do?
– Vineet Kumar Doshi
Aug 25 '15 at 9:04
6
@VineetKumarDoshi: Here it is used to unpcak a list into multiple arguments to the function call. Read more here: stackoverflow.com/questions/36901/…
– Moberg
Sep 15 '15 at 6:20
3
Note: This works only if each list contains at least one item
– igo
Sep 13 '17 at 12:35
|
show 2 more comments
In Python 2.6+
import itertools
for element in itertools.product(*somelists):
print(element)
Documentation:
Python 3 - itertools.product
In Python 2.6+
import itertools
for element in itertools.product(*somelists):
print(element)
Documentation:
Python 3 - itertools.product
edited Apr 20 '17 at 5:52
Rufflewind
6,65712443
6,65712443
answered Feb 10 '09 at 19:58
TriptychTriptych
155k29135165
155k29135165
19
Just wanted to add the '*' character is required if you use the variable somelists as provided by the OP.
– brian buck
Jan 13 '11 at 22:51
1
@jaska:product()
generatesnitems_in_a_list ** nlists
elements in the result (reduce(mul, map(len, somelists))
). There is no reason to believe that yielding a single element is notO(nlists)
(amortized) i.e., the time complexity is the same as for simple nestedfor
-loops e.g., for the input in the question:nlists=3
, total number of elements in the result:3*2*2
, and each element hasnlists
items (3
in this case).
– jfs
Aug 14 '15 at 22:08
2
What is the use of*
before somelists? What does it do?
– Vineet Kumar Doshi
Aug 25 '15 at 9:04
6
@VineetKumarDoshi: Here it is used to unpcak a list into multiple arguments to the function call. Read more here: stackoverflow.com/questions/36901/…
– Moberg
Sep 15 '15 at 6:20
3
Note: This works only if each list contains at least one item
– igo
Sep 13 '17 at 12:35
|
show 2 more comments
19
Just wanted to add the '*' character is required if you use the variable somelists as provided by the OP.
– brian buck
Jan 13 '11 at 22:51
1
@jaska:product()
generatesnitems_in_a_list ** nlists
elements in the result (reduce(mul, map(len, somelists))
). There is no reason to believe that yielding a single element is notO(nlists)
(amortized) i.e., the time complexity is the same as for simple nestedfor
-loops e.g., for the input in the question:nlists=3
, total number of elements in the result:3*2*2
, and each element hasnlists
items (3
in this case).
– jfs
Aug 14 '15 at 22:08
2
What is the use of*
before somelists? What does it do?
– Vineet Kumar Doshi
Aug 25 '15 at 9:04
6
@VineetKumarDoshi: Here it is used to unpcak a list into multiple arguments to the function call. Read more here: stackoverflow.com/questions/36901/…
– Moberg
Sep 15 '15 at 6:20
3
Note: This works only if each list contains at least one item
– igo
Sep 13 '17 at 12:35
19
19
Just wanted to add the '*' character is required if you use the variable somelists as provided by the OP.
– brian buck
Jan 13 '11 at 22:51
Just wanted to add the '*' character is required if you use the variable somelists as provided by the OP.
– brian buck
Jan 13 '11 at 22:51
1
1
@jaska:
product()
generates nitems_in_a_list ** nlists
elements in the result (reduce(mul, map(len, somelists))
). There is no reason to believe that yielding a single element is not O(nlists)
(amortized) i.e., the time complexity is the same as for simple nested for
-loops e.g., for the input in the question: nlists=3
, total number of elements in the result: 3*2*2
, and each element has nlists
items (3
in this case).– jfs
Aug 14 '15 at 22:08
@jaska:
product()
generates nitems_in_a_list ** nlists
elements in the result (reduce(mul, map(len, somelists))
). There is no reason to believe that yielding a single element is not O(nlists)
(amortized) i.e., the time complexity is the same as for simple nested for
-loops e.g., for the input in the question: nlists=3
, total number of elements in the result: 3*2*2
, and each element has nlists
items (3
in this case).– jfs
Aug 14 '15 at 22:08
2
2
What is the use of
*
before somelists? What does it do?– Vineet Kumar Doshi
Aug 25 '15 at 9:04
What is the use of
*
before somelists? What does it do?– Vineet Kumar Doshi
Aug 25 '15 at 9:04
6
6
@VineetKumarDoshi: Here it is used to unpcak a list into multiple arguments to the function call. Read more here: stackoverflow.com/questions/36901/…
– Moberg
Sep 15 '15 at 6:20
@VineetKumarDoshi: Here it is used to unpcak a list into multiple arguments to the function call. Read more here: stackoverflow.com/questions/36901/…
– Moberg
Sep 15 '15 at 6:20
3
3
Note: This works only if each list contains at least one item
– igo
Sep 13 '17 at 12:35
Note: This works only if each list contains at least one item
– igo
Sep 13 '17 at 12:35
|
show 2 more comments
import itertools
>>> for i in itertools.product([1,2,3],['a','b'],[4,5]):
... print i
...
(1, 'a', 4)
(1, 'a', 5)
(1, 'b', 4)
(1, 'b', 5)
(2, 'a', 4)
(2, 'a', 5)
(2, 'b', 4)
(2, 'b', 5)
(3, 'a', 4)
(3, 'a', 5)
(3, 'b', 4)
(3, 'b', 5)
>>>
add a comment |
import itertools
>>> for i in itertools.product([1,2,3],['a','b'],[4,5]):
... print i
...
(1, 'a', 4)
(1, 'a', 5)
(1, 'b', 4)
(1, 'b', 5)
(2, 'a', 4)
(2, 'a', 5)
(2, 'b', 4)
(2, 'b', 5)
(3, 'a', 4)
(3, 'a', 5)
(3, 'b', 4)
(3, 'b', 5)
>>>
add a comment |
import itertools
>>> for i in itertools.product([1,2,3],['a','b'],[4,5]):
... print i
...
(1, 'a', 4)
(1, 'a', 5)
(1, 'b', 4)
(1, 'b', 5)
(2, 'a', 4)
(2, 'a', 5)
(2, 'b', 4)
(2, 'b', 5)
(3, 'a', 4)
(3, 'a', 5)
(3, 'b', 4)
(3, 'b', 5)
>>>
import itertools
>>> for i in itertools.product([1,2,3],['a','b'],[4,5]):
... print i
...
(1, 'a', 4)
(1, 'a', 5)
(1, 'b', 4)
(1, 'b', 5)
(2, 'a', 4)
(2, 'a', 5)
(2, 'b', 4)
(2, 'b', 5)
(3, 'a', 4)
(3, 'a', 5)
(3, 'b', 4)
(3, 'b', 5)
>>>
answered Feb 10 '09 at 19:58
Jason BakerJason Baker
106k109334488
106k109334488
add a comment |
add a comment |
For Python 2.5 and older:
>>> [(a, b, c) for a in [1,2,3] for b in ['a','b'] for c in [4,5]]
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4),
(2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5),
(3, 'b', 4), (3, 'b', 5)]
Here's a recursive version of product()
(just an illustration):
def product(*args):
if not args:
return iter(((),)) # yield tuple()
return (items + (item,)
for items in product(*args[:-1]) for item in args[-1])
Example:
>>> list(product([1,2,3], ['a','b'], [4,5]))
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4),
(2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5),
(3, 'b', 4), (3, 'b', 5)]
>>> list(product([1,2,3]))
[(1,), (2,), (3,)]
>>> list(product())
>>> list(product())
[()]
The recursive version doesn't work if some ofargs
are iterators.
– jfs
Feb 10 '09 at 21:43
add a comment |
For Python 2.5 and older:
>>> [(a, b, c) for a in [1,2,3] for b in ['a','b'] for c in [4,5]]
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4),
(2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5),
(3, 'b', 4), (3, 'b', 5)]
Here's a recursive version of product()
(just an illustration):
def product(*args):
if not args:
return iter(((),)) # yield tuple()
return (items + (item,)
for items in product(*args[:-1]) for item in args[-1])
Example:
>>> list(product([1,2,3], ['a','b'], [4,5]))
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4),
(2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5),
(3, 'b', 4), (3, 'b', 5)]
>>> list(product([1,2,3]))
[(1,), (2,), (3,)]
>>> list(product())
>>> list(product())
[()]
The recursive version doesn't work if some ofargs
are iterators.
– jfs
Feb 10 '09 at 21:43
add a comment |
For Python 2.5 and older:
>>> [(a, b, c) for a in [1,2,3] for b in ['a','b'] for c in [4,5]]
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4),
(2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5),
(3, 'b', 4), (3, 'b', 5)]
Here's a recursive version of product()
(just an illustration):
def product(*args):
if not args:
return iter(((),)) # yield tuple()
return (items + (item,)
for items in product(*args[:-1]) for item in args[-1])
Example:
>>> list(product([1,2,3], ['a','b'], [4,5]))
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4),
(2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5),
(3, 'b', 4), (3, 'b', 5)]
>>> list(product([1,2,3]))
[(1,), (2,), (3,)]
>>> list(product())
>>> list(product())
[()]
For Python 2.5 and older:
>>> [(a, b, c) for a in [1,2,3] for b in ['a','b'] for c in [4,5]]
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4),
(2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5),
(3, 'b', 4), (3, 'b', 5)]
Here's a recursive version of product()
(just an illustration):
def product(*args):
if not args:
return iter(((),)) # yield tuple()
return (items + (item,)
for items in product(*args[:-1]) for item in args[-1])
Example:
>>> list(product([1,2,3], ['a','b'], [4,5]))
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4),
(2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5),
(3, 'b', 4), (3, 'b', 5)]
>>> list(product([1,2,3]))
[(1,), (2,), (3,)]
>>> list(product())
>>> list(product())
[()]
edited Feb 10 '09 at 21:30
answered Feb 10 '09 at 20:38
jfsjfs
266k815611102
266k815611102
The recursive version doesn't work if some ofargs
are iterators.
– jfs
Feb 10 '09 at 21:43
add a comment |
The recursive version doesn't work if some ofargs
are iterators.
– jfs
Feb 10 '09 at 21:43
The recursive version doesn't work if some of
args
are iterators.– jfs
Feb 10 '09 at 21:43
The recursive version doesn't work if some of
args
are iterators.– jfs
Feb 10 '09 at 21:43
add a comment |
with itertools.product:
import itertools
result = list(itertools.product(*somelists))
5
What is the use of*
before somelists?
– Vineet Kumar Doshi
Aug 25 '15 at 9:04
@VineetKumarDoshi "product(somelists)" is a cartesian product between the sublists in a way that Python first get "[1, 2, 3]" as an element and then gets other element after next comman and that is linebreak so the first product term is ([1, 2, 3],), similary for the second ([4, 5],) and so "[([1, 2, 3],), ([4, 5],), ([6, 7],)]". If you wanna get a cartesian product between elements inside the tuples, you need to tell Python with Asterisk about the tuple structure. For dictionary, you use **. More here.
– hhh
Feb 15 '16 at 23:13
add a comment |
with itertools.product:
import itertools
result = list(itertools.product(*somelists))
5
What is the use of*
before somelists?
– Vineet Kumar Doshi
Aug 25 '15 at 9:04
@VineetKumarDoshi "product(somelists)" is a cartesian product between the sublists in a way that Python first get "[1, 2, 3]" as an element and then gets other element after next comman and that is linebreak so the first product term is ([1, 2, 3],), similary for the second ([4, 5],) and so "[([1, 2, 3],), ([4, 5],), ([6, 7],)]". If you wanna get a cartesian product between elements inside the tuples, you need to tell Python with Asterisk about the tuple structure. For dictionary, you use **. More here.
– hhh
Feb 15 '16 at 23:13
add a comment |
with itertools.product:
import itertools
result = list(itertools.product(*somelists))
with itertools.product:
import itertools
result = list(itertools.product(*somelists))
edited Jan 1 '10 at 17:03
answered Feb 10 '09 at 20:01
SilentGhostSilentGhost
195k47266263
195k47266263
5
What is the use of*
before somelists?
– Vineet Kumar Doshi
Aug 25 '15 at 9:04
@VineetKumarDoshi "product(somelists)" is a cartesian product between the sublists in a way that Python first get "[1, 2, 3]" as an element and then gets other element after next comman and that is linebreak so the first product term is ([1, 2, 3],), similary for the second ([4, 5],) and so "[([1, 2, 3],), ([4, 5],), ([6, 7],)]". If you wanna get a cartesian product between elements inside the tuples, you need to tell Python with Asterisk about the tuple structure. For dictionary, you use **. More here.
– hhh
Feb 15 '16 at 23:13
add a comment |
5
What is the use of*
before somelists?
– Vineet Kumar Doshi
Aug 25 '15 at 9:04
@VineetKumarDoshi "product(somelists)" is a cartesian product between the sublists in a way that Python first get "[1, 2, 3]" as an element and then gets other element after next comman and that is linebreak so the first product term is ([1, 2, 3],), similary for the second ([4, 5],) and so "[([1, 2, 3],), ([4, 5],), ([6, 7],)]". If you wanna get a cartesian product between elements inside the tuples, you need to tell Python with Asterisk about the tuple structure. For dictionary, you use **. More here.
– hhh
Feb 15 '16 at 23:13
5
5
What is the use of
*
before somelists?– Vineet Kumar Doshi
Aug 25 '15 at 9:04
What is the use of
*
before somelists?– Vineet Kumar Doshi
Aug 25 '15 at 9:04
@VineetKumarDoshi "product(somelists)" is a cartesian product between the sublists in a way that Python first get "[1, 2, 3]" as an element and then gets other element after next comman and that is linebreak so the first product term is ([1, 2, 3],), similary for the second ([4, 5],) and so "[([1, 2, 3],), ([4, 5],), ([6, 7],)]". If you wanna get a cartesian product between elements inside the tuples, you need to tell Python with Asterisk about the tuple structure. For dictionary, you use **. More here.
– hhh
Feb 15 '16 at 23:13
@VineetKumarDoshi "product(somelists)" is a cartesian product between the sublists in a way that Python first get "[1, 2, 3]" as an element and then gets other element after next comman and that is linebreak so the first product term is ([1, 2, 3],), similary for the second ([4, 5],) and so "[([1, 2, 3],), ([4, 5],), ([6, 7],)]". If you wanna get a cartesian product between elements inside the tuples, you need to tell Python with Asterisk about the tuple structure. For dictionary, you use **. More here.
– hhh
Feb 15 '16 at 23:13
add a comment |
In Python 2.6 and above you can use 'itertools.product`. In older versions of Python you can use the following (almost -- see documentation) equivalent code from the documentation, at least as a starting point:
def product(*args, **kwds):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
pools = map(tuple, args) * kwds.get('repeat', 1)
result = []
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
The result of both is an iterator, so if you really need a list for furthert processing, use list(result)
.
Per the documentation, the actual itertools.product implementation does NOT build intermediate results, which could be expensive. Using this technique could get out of hand quite quickly for moderately sized lists.
– Triptych
Feb 10 '09 at 20:05
3
i can only point the OP to the documentation, not read it for him.
– user3850
Feb 10 '09 at 20:19
1
The code from the documentation is meant to demonstrate what the product function does, not as a workaround for earlier versions of Python.
– Triptych
Mar 10 '09 at 21:07
2
your point being?
– user3850
Mar 10 '09 at 22:37
add a comment |
In Python 2.6 and above you can use 'itertools.product`. In older versions of Python you can use the following (almost -- see documentation) equivalent code from the documentation, at least as a starting point:
def product(*args, **kwds):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
pools = map(tuple, args) * kwds.get('repeat', 1)
result = []
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
The result of both is an iterator, so if you really need a list for furthert processing, use list(result)
.
Per the documentation, the actual itertools.product implementation does NOT build intermediate results, which could be expensive. Using this technique could get out of hand quite quickly for moderately sized lists.
– Triptych
Feb 10 '09 at 20:05
3
i can only point the OP to the documentation, not read it for him.
– user3850
Feb 10 '09 at 20:19
1
The code from the documentation is meant to demonstrate what the product function does, not as a workaround for earlier versions of Python.
– Triptych
Mar 10 '09 at 21:07
2
your point being?
– user3850
Mar 10 '09 at 22:37
add a comment |
In Python 2.6 and above you can use 'itertools.product`. In older versions of Python you can use the following (almost -- see documentation) equivalent code from the documentation, at least as a starting point:
def product(*args, **kwds):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
pools = map(tuple, args) * kwds.get('repeat', 1)
result = []
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
The result of both is an iterator, so if you really need a list for furthert processing, use list(result)
.
In Python 2.6 and above you can use 'itertools.product`. In older versions of Python you can use the following (almost -- see documentation) equivalent code from the documentation, at least as a starting point:
def product(*args, **kwds):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
pools = map(tuple, args) * kwds.get('repeat', 1)
result = []
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
The result of both is an iterator, so if you really need a list for furthert processing, use list(result)
.
edited Jan 5 '17 at 14:30
answered Feb 10 '09 at 20:02
user3850
Per the documentation, the actual itertools.product implementation does NOT build intermediate results, which could be expensive. Using this technique could get out of hand quite quickly for moderately sized lists.
– Triptych
Feb 10 '09 at 20:05
3
i can only point the OP to the documentation, not read it for him.
– user3850
Feb 10 '09 at 20:19
1
The code from the documentation is meant to demonstrate what the product function does, not as a workaround for earlier versions of Python.
– Triptych
Mar 10 '09 at 21:07
2
your point being?
– user3850
Mar 10 '09 at 22:37
add a comment |
Per the documentation, the actual itertools.product implementation does NOT build intermediate results, which could be expensive. Using this technique could get out of hand quite quickly for moderately sized lists.
– Triptych
Feb 10 '09 at 20:05
3
i can only point the OP to the documentation, not read it for him.
– user3850
Feb 10 '09 at 20:19
1
The code from the documentation is meant to demonstrate what the product function does, not as a workaround for earlier versions of Python.
– Triptych
Mar 10 '09 at 21:07
2
your point being?
– user3850
Mar 10 '09 at 22:37
Per the documentation, the actual itertools.product implementation does NOT build intermediate results, which could be expensive. Using this technique could get out of hand quite quickly for moderately sized lists.
– Triptych
Feb 10 '09 at 20:05
Per the documentation, the actual itertools.product implementation does NOT build intermediate results, which could be expensive. Using this technique could get out of hand quite quickly for moderately sized lists.
– Triptych
Feb 10 '09 at 20:05
3
3
i can only point the OP to the documentation, not read it for him.
– user3850
Feb 10 '09 at 20:19
i can only point the OP to the documentation, not read it for him.
– user3850
Feb 10 '09 at 20:19
1
1
The code from the documentation is meant to demonstrate what the product function does, not as a workaround for earlier versions of Python.
– Triptych
Mar 10 '09 at 21:07
The code from the documentation is meant to demonstrate what the product function does, not as a workaround for earlier versions of Python.
– Triptych
Mar 10 '09 at 21:07
2
2
your point being?
– user3850
Mar 10 '09 at 22:37
your point being?
– user3850
Mar 10 '09 at 22:37
add a comment |
I would use list comprehension :
somelists = [
[1, 2, 3],
['a', 'b'],
[4, 5]
]
cart_prod = [(a,b,c) for a in somelists[0] for b in somelists[1] for c in somelists[2]]
I really like this solution using list comprehensions. I don't know why isn't upvoted more, it's so simple.
– llekn
Nov 30 '16 at 17:38
9
@llekn because the code seems to be fixed to the number of lists
– Bằng Rikimaru
Jan 16 '17 at 15:33
add a comment |
I would use list comprehension :
somelists = [
[1, 2, 3],
['a', 'b'],
[4, 5]
]
cart_prod = [(a,b,c) for a in somelists[0] for b in somelists[1] for c in somelists[2]]
I really like this solution using list comprehensions. I don't know why isn't upvoted more, it's so simple.
– llekn
Nov 30 '16 at 17:38
9
@llekn because the code seems to be fixed to the number of lists
– Bằng Rikimaru
Jan 16 '17 at 15:33
add a comment |
I would use list comprehension :
somelists = [
[1, 2, 3],
['a', 'b'],
[4, 5]
]
cart_prod = [(a,b,c) for a in somelists[0] for b in somelists[1] for c in somelists[2]]
I would use list comprehension :
somelists = [
[1, 2, 3],
['a', 'b'],
[4, 5]
]
cart_prod = [(a,b,c) for a in somelists[0] for b in somelists[1] for c in somelists[2]]
answered Nov 21 '16 at 8:42
user1035648user1035648
13416
13416
I really like this solution using list comprehensions. I don't know why isn't upvoted more, it's so simple.
– llekn
Nov 30 '16 at 17:38
9
@llekn because the code seems to be fixed to the number of lists
– Bằng Rikimaru
Jan 16 '17 at 15:33
add a comment |
I really like this solution using list comprehensions. I don't know why isn't upvoted more, it's so simple.
– llekn
Nov 30 '16 at 17:38
9
@llekn because the code seems to be fixed to the number of lists
– Bằng Rikimaru
Jan 16 '17 at 15:33
I really like this solution using list comprehensions. I don't know why isn't upvoted more, it's so simple.
– llekn
Nov 30 '16 at 17:38
I really like this solution using list comprehensions. I don't know why isn't upvoted more, it's so simple.
– llekn
Nov 30 '16 at 17:38
9
9
@llekn because the code seems to be fixed to the number of lists
– Bằng Rikimaru
Jan 16 '17 at 15:33
@llekn because the code seems to be fixed to the number of lists
– Bằng Rikimaru
Jan 16 '17 at 15:33
add a comment |
Here is a recursive generator, which doesn't store any temporary lists
def product(ar_list):
if not ar_list:
yield ()
else:
for a in ar_list[0]:
for prod in product(ar_list[1:]):
yield (a,)+prod
print list(product([[1,2],[3,4],[5,6]]))
Output:
[(1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6)]
1
They're stored in the stack, though.
– Quentin Pradet
Mar 16 '15 at 11:09
@QuentinPradet do you mean a generator likedef f(): while True: yield 1
will keep on increasing its stack size as we go through it?
– Anurag Uniyal
Mar 16 '15 at 22:42
no, but def f(): yield 1; f() will, right?
– Quentin Pradet
Mar 17 '15 at 10:09
@QuentinPradet yeah, but even in this case only the stack needed for max depth, not the whole list, so in this case stack of 3
– Anurag Uniyal
Mar 17 '15 at 16:14
It's true, sorry. A benchmark could be interesting. :)
– Quentin Pradet
Mar 17 '15 at 18:24
add a comment |
Here is a recursive generator, which doesn't store any temporary lists
def product(ar_list):
if not ar_list:
yield ()
else:
for a in ar_list[0]:
for prod in product(ar_list[1:]):
yield (a,)+prod
print list(product([[1,2],[3,4],[5,6]]))
Output:
[(1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6)]
1
They're stored in the stack, though.
– Quentin Pradet
Mar 16 '15 at 11:09
@QuentinPradet do you mean a generator likedef f(): while True: yield 1
will keep on increasing its stack size as we go through it?
– Anurag Uniyal
Mar 16 '15 at 22:42
no, but def f(): yield 1; f() will, right?
– Quentin Pradet
Mar 17 '15 at 10:09
@QuentinPradet yeah, but even in this case only the stack needed for max depth, not the whole list, so in this case stack of 3
– Anurag Uniyal
Mar 17 '15 at 16:14
It's true, sorry. A benchmark could be interesting. :)
– Quentin Pradet
Mar 17 '15 at 18:24
add a comment |
Here is a recursive generator, which doesn't store any temporary lists
def product(ar_list):
if not ar_list:
yield ()
else:
for a in ar_list[0]:
for prod in product(ar_list[1:]):
yield (a,)+prod
print list(product([[1,2],[3,4],[5,6]]))
Output:
[(1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6)]
Here is a recursive generator, which doesn't store any temporary lists
def product(ar_list):
if not ar_list:
yield ()
else:
for a in ar_list[0]:
for prod in product(ar_list[1:]):
yield (a,)+prod
print list(product([[1,2],[3,4],[5,6]]))
Output:
[(1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6)]
answered Jun 14 '13 at 6:08
Anurag UniyalAnurag Uniyal
55.6k28148198
55.6k28148198
1
They're stored in the stack, though.
– Quentin Pradet
Mar 16 '15 at 11:09
@QuentinPradet do you mean a generator likedef f(): while True: yield 1
will keep on increasing its stack size as we go through it?
– Anurag Uniyal
Mar 16 '15 at 22:42
no, but def f(): yield 1; f() will, right?
– Quentin Pradet
Mar 17 '15 at 10:09
@QuentinPradet yeah, but even in this case only the stack needed for max depth, not the whole list, so in this case stack of 3
– Anurag Uniyal
Mar 17 '15 at 16:14
It's true, sorry. A benchmark could be interesting. :)
– Quentin Pradet
Mar 17 '15 at 18:24
add a comment |
1
They're stored in the stack, though.
– Quentin Pradet
Mar 16 '15 at 11:09
@QuentinPradet do you mean a generator likedef f(): while True: yield 1
will keep on increasing its stack size as we go through it?
– Anurag Uniyal
Mar 16 '15 at 22:42
no, but def f(): yield 1; f() will, right?
– Quentin Pradet
Mar 17 '15 at 10:09
@QuentinPradet yeah, but even in this case only the stack needed for max depth, not the whole list, so in this case stack of 3
– Anurag Uniyal
Mar 17 '15 at 16:14
It's true, sorry. A benchmark could be interesting. :)
– Quentin Pradet
Mar 17 '15 at 18:24
1
1
They're stored in the stack, though.
– Quentin Pradet
Mar 16 '15 at 11:09
They're stored in the stack, though.
– Quentin Pradet
Mar 16 '15 at 11:09
@QuentinPradet do you mean a generator like
def f(): while True: yield 1
will keep on increasing its stack size as we go through it?– Anurag Uniyal
Mar 16 '15 at 22:42
@QuentinPradet do you mean a generator like
def f(): while True: yield 1
will keep on increasing its stack size as we go through it?– Anurag Uniyal
Mar 16 '15 at 22:42
no, but def f(): yield 1; f() will, right?
– Quentin Pradet
Mar 17 '15 at 10:09
no, but def f(): yield 1; f() will, right?
– Quentin Pradet
Mar 17 '15 at 10:09
@QuentinPradet yeah, but even in this case only the stack needed for max depth, not the whole list, so in this case stack of 3
– Anurag Uniyal
Mar 17 '15 at 16:14
@QuentinPradet yeah, but even in this case only the stack needed for max depth, not the whole list, so in this case stack of 3
– Anurag Uniyal
Mar 17 '15 at 16:14
It's true, sorry. A benchmark could be interesting. :)
– Quentin Pradet
Mar 17 '15 at 18:24
It's true, sorry. A benchmark could be interesting. :)
– Quentin Pradet
Mar 17 '15 at 18:24
add a comment |
Although there are many answers already, I would like to share some of my thoughts:
Iterative approach
def cartesian_iterative(pools):
result = []
for pool in pools:
result = [x+[y] for x in result for y in pool]
return result
Recursive Approach
def cartesian_recursive(pools):
if len(pools) > 2:
pools[0] = product(pools[0], pools[1])
del pools[1]
return cartesian_recursive(pools)
else:
pools[0] = product(pools[0], pools[1])
del pools[1]
return pools
def product(x, y):
return [xx + [yy] if isinstance(xx, list) else [xx] + [yy] for xx in x for yy in y]
Lambda Approach
def cartesian_reduct(pools):
return reduce(lambda x,y: product(x,y) , pools)
In "Iterative Approach", why is result declared as result = [] I know that it is list_of_list but in general even if we have declare list_of_list we use and not []
– Sachin S
Jul 16 '17 at 15:44
I'm a bit of a newby in terms of Pythonic solutions. Would you or some passerby please write the list comprehension in the "iterative approach" in separate loops?
– Johnny Boy
Dec 10 '18 at 17:03
add a comment |
Although there are many answers already, I would like to share some of my thoughts:
Iterative approach
def cartesian_iterative(pools):
result = []
for pool in pools:
result = [x+[y] for x in result for y in pool]
return result
Recursive Approach
def cartesian_recursive(pools):
if len(pools) > 2:
pools[0] = product(pools[0], pools[1])
del pools[1]
return cartesian_recursive(pools)
else:
pools[0] = product(pools[0], pools[1])
del pools[1]
return pools
def product(x, y):
return [xx + [yy] if isinstance(xx, list) else [xx] + [yy] for xx in x for yy in y]
Lambda Approach
def cartesian_reduct(pools):
return reduce(lambda x,y: product(x,y) , pools)
In "Iterative Approach", why is result declared as result = [] I know that it is list_of_list but in general even if we have declare list_of_list we use and not []
– Sachin S
Jul 16 '17 at 15:44
I'm a bit of a newby in terms of Pythonic solutions. Would you or some passerby please write the list comprehension in the "iterative approach" in separate loops?
– Johnny Boy
Dec 10 '18 at 17:03
add a comment |
Although there are many answers already, I would like to share some of my thoughts:
Iterative approach
def cartesian_iterative(pools):
result = []
for pool in pools:
result = [x+[y] for x in result for y in pool]
return result
Recursive Approach
def cartesian_recursive(pools):
if len(pools) > 2:
pools[0] = product(pools[0], pools[1])
del pools[1]
return cartesian_recursive(pools)
else:
pools[0] = product(pools[0], pools[1])
del pools[1]
return pools
def product(x, y):
return [xx + [yy] if isinstance(xx, list) else [xx] + [yy] for xx in x for yy in y]
Lambda Approach
def cartesian_reduct(pools):
return reduce(lambda x,y: product(x,y) , pools)
Although there are many answers already, I would like to share some of my thoughts:
Iterative approach
def cartesian_iterative(pools):
result = []
for pool in pools:
result = [x+[y] for x in result for y in pool]
return result
Recursive Approach
def cartesian_recursive(pools):
if len(pools) > 2:
pools[0] = product(pools[0], pools[1])
del pools[1]
return cartesian_recursive(pools)
else:
pools[0] = product(pools[0], pools[1])
del pools[1]
return pools
def product(x, y):
return [xx + [yy] if isinstance(xx, list) else [xx] + [yy] for xx in x for yy in y]
Lambda Approach
def cartesian_reduct(pools):
return reduce(lambda x,y: product(x,y) , pools)
edited Feb 21 '17 at 6:40
Matthew Beckman
1,15721025
1,15721025
answered Feb 21 '17 at 4:03
weiyixieweiyixie
22733
22733
In "Iterative Approach", why is result declared as result = [] I know that it is list_of_list but in general even if we have declare list_of_list we use and not []
– Sachin S
Jul 16 '17 at 15:44
I'm a bit of a newby in terms of Pythonic solutions. Would you or some passerby please write the list comprehension in the "iterative approach" in separate loops?
– Johnny Boy
Dec 10 '18 at 17:03
add a comment |
In "Iterative Approach", why is result declared as result = [] I know that it is list_of_list but in general even if we have declare list_of_list we use and not []
– Sachin S
Jul 16 '17 at 15:44
I'm a bit of a newby in terms of Pythonic solutions. Would you or some passerby please write the list comprehension in the "iterative approach" in separate loops?
– Johnny Boy
Dec 10 '18 at 17:03
In "Iterative Approach", why is result declared as result = [] I know that it is list_of_list but in general even if we have declare list_of_list we use and not []
– Sachin S
Jul 16 '17 at 15:44
In "Iterative Approach", why is result declared as result = [] I know that it is list_of_list but in general even if we have declare list_of_list we use and not []
– Sachin S
Jul 16 '17 at 15:44
I'm a bit of a newby in terms of Pythonic solutions. Would you or some passerby please write the list comprehension in the "iterative approach" in separate loops?
– Johnny Boy
Dec 10 '18 at 17:03
I'm a bit of a newby in terms of Pythonic solutions. Would you or some passerby please write the list comprehension in the "iterative approach" in separate loops?
– Johnny Boy
Dec 10 '18 at 17:03
add a comment |
Just to add a bit to what has already been said: if you use sympy, you can use symbols rather than strings which makes them mathematically useful.
import itertools
import sympy
x, y = sympy.symbols('x y')
somelist = [[x,y], [1,2,3], [4,5]]
somelist2 = [[1,2], [1,2,3], [4,5]]
for element in itertools.product(*somelist):
print element
About sympy.
add a comment |
Just to add a bit to what has already been said: if you use sympy, you can use symbols rather than strings which makes them mathematically useful.
import itertools
import sympy
x, y = sympy.symbols('x y')
somelist = [[x,y], [1,2,3], [4,5]]
somelist2 = [[1,2], [1,2,3], [4,5]]
for element in itertools.product(*somelist):
print element
About sympy.
add a comment |
Just to add a bit to what has already been said: if you use sympy, you can use symbols rather than strings which makes them mathematically useful.
import itertools
import sympy
x, y = sympy.symbols('x y')
somelist = [[x,y], [1,2,3], [4,5]]
somelist2 = [[1,2], [1,2,3], [4,5]]
for element in itertools.product(*somelist):
print element
About sympy.
Just to add a bit to what has already been said: if you use sympy, you can use symbols rather than strings which makes them mathematically useful.
import itertools
import sympy
x, y = sympy.symbols('x y')
somelist = [[x,y], [1,2,3], [4,5]]
somelist2 = [[1,2], [1,2,3], [4,5]]
for element in itertools.product(*somelist):
print element
About sympy.
edited Jun 8 '16 at 6:47
FengYao
114
114
answered Oct 29 '15 at 22:28
Tyler HeersTyler Heers
1164
1164
add a comment |
add a comment |
A minor modification to the above recursive generator solution in variadic flavor:
def product_args(*args):
if args:
for a in args[0]:
for prod in product_args(*args[1:]) if args[1:] else ((),):
yield (a,) + prod
And of course a wrapper which makes it work exactly the same as that solution:
def product2(ar_list):
"""
>>> list(product(()))
[()]
>>> list(product2(()))
"""
return product_args(*ar_list)
with one trade-off: it checks if recursion should break upon each outer loop, and one gain: no yield upon empty call, e.g.product(())
, which I suppose would be semantically more correct (see the doctest).
Regarding list comprehension: the mathematical definition applies to an arbitrary number of arguments, while list comprehension could only deal with a known number of them.
add a comment |
A minor modification to the above recursive generator solution in variadic flavor:
def product_args(*args):
if args:
for a in args[0]:
for prod in product_args(*args[1:]) if args[1:] else ((),):
yield (a,) + prod
And of course a wrapper which makes it work exactly the same as that solution:
def product2(ar_list):
"""
>>> list(product(()))
[()]
>>> list(product2(()))
"""
return product_args(*ar_list)
with one trade-off: it checks if recursion should break upon each outer loop, and one gain: no yield upon empty call, e.g.product(())
, which I suppose would be semantically more correct (see the doctest).
Regarding list comprehension: the mathematical definition applies to an arbitrary number of arguments, while list comprehension could only deal with a known number of them.
add a comment |
A minor modification to the above recursive generator solution in variadic flavor:
def product_args(*args):
if args:
for a in args[0]:
for prod in product_args(*args[1:]) if args[1:] else ((),):
yield (a,) + prod
And of course a wrapper which makes it work exactly the same as that solution:
def product2(ar_list):
"""
>>> list(product(()))
[()]
>>> list(product2(()))
"""
return product_args(*ar_list)
with one trade-off: it checks if recursion should break upon each outer loop, and one gain: no yield upon empty call, e.g.product(())
, which I suppose would be semantically more correct (see the doctest).
Regarding list comprehension: the mathematical definition applies to an arbitrary number of arguments, while list comprehension could only deal with a known number of them.
A minor modification to the above recursive generator solution in variadic flavor:
def product_args(*args):
if args:
for a in args[0]:
for prod in product_args(*args[1:]) if args[1:] else ((),):
yield (a,) + prod
And of course a wrapper which makes it work exactly the same as that solution:
def product2(ar_list):
"""
>>> list(product(()))
[()]
>>> list(product2(()))
"""
return product_args(*ar_list)
with one trade-off: it checks if recursion should break upon each outer loop, and one gain: no yield upon empty call, e.g.product(())
, which I suppose would be semantically more correct (see the doctest).
Regarding list comprehension: the mathematical definition applies to an arbitrary number of arguments, while list comprehension could only deal with a known number of them.
edited Jan 11 '18 at 22:56
user3759769
52
52
answered Dec 10 '16 at 1:40
Mike LuMike Lu
212
212
add a comment |
add a comment |
Recursive Approach:
def rec_cart(start, array, partial, results):
if len(partial) == len(array):
results.append(partial)
return
for element in array[start]:
rec_cart(start+1, array, partial+[element], results)
rec_res =
some_lists = [[1, 2, 3], ['a', 'b'], [4, 5]]
rec_cart(0, some_lists, , rec_res)
print(rec_res)
Iterative Approach:
def itr_cart(array):
results = []
for i in range(len(array)):
temp =
for res in results:
for element in array[i]:
temp.append(res+[element])
results = temp
return results
some_lists = [[1, 2, 3], ['a', 'b'], [4, 5]]
itr_res = itr_cart(some_lists)
print(itr_res)
add a comment |
Recursive Approach:
def rec_cart(start, array, partial, results):
if len(partial) == len(array):
results.append(partial)
return
for element in array[start]:
rec_cart(start+1, array, partial+[element], results)
rec_res =
some_lists = [[1, 2, 3], ['a', 'b'], [4, 5]]
rec_cart(0, some_lists, , rec_res)
print(rec_res)
Iterative Approach:
def itr_cart(array):
results = []
for i in range(len(array)):
temp =
for res in results:
for element in array[i]:
temp.append(res+[element])
results = temp
return results
some_lists = [[1, 2, 3], ['a', 'b'], [4, 5]]
itr_res = itr_cart(some_lists)
print(itr_res)
add a comment |
Recursive Approach:
def rec_cart(start, array, partial, results):
if len(partial) == len(array):
results.append(partial)
return
for element in array[start]:
rec_cart(start+1, array, partial+[element], results)
rec_res =
some_lists = [[1, 2, 3], ['a', 'b'], [4, 5]]
rec_cart(0, some_lists, , rec_res)
print(rec_res)
Iterative Approach:
def itr_cart(array):
results = []
for i in range(len(array)):
temp =
for res in results:
for element in array[i]:
temp.append(res+[element])
results = temp
return results
some_lists = [[1, 2, 3], ['a', 'b'], [4, 5]]
itr_res = itr_cart(some_lists)
print(itr_res)
Recursive Approach:
def rec_cart(start, array, partial, results):
if len(partial) == len(array):
results.append(partial)
return
for element in array[start]:
rec_cart(start+1, array, partial+[element], results)
rec_res =
some_lists = [[1, 2, 3], ['a', 'b'], [4, 5]]
rec_cart(0, some_lists, , rec_res)
print(rec_res)
Iterative Approach:
def itr_cart(array):
results = []
for i in range(len(array)):
temp =
for res in results:
for element in array[i]:
temp.append(res+[element])
results = temp
return results
some_lists = [[1, 2, 3], ['a', 'b'], [4, 5]]
itr_res = itr_cart(some_lists)
print(itr_res)
answered Dec 31 '18 at 18:32
JaiJai
1,5722616
1,5722616
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f533905%2fget-the-cartesian-product-of-a-series-of-lists%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
15
be aware that 'every possible combination' is not quite the same as 'Cartesian product', since in Cartesian products, duplicates are allowed.
– Triptych
Feb 10 '09 at 20:08
6
Is there a non duplicate version of cartesian product?
– KJW
Nov 13 '13 at 5:32
9
@KJW Yes,
set(cartesian product)
– NoBugs
Feb 12 '15 at 7:04
4
There should be no duplicates in a Cartesian product, unless the input lists contain duplicates themselves. If you want no duplicates in the Cartesian product, use
set(inputlist)
over all your input lists. Not on the result.– CamilB
Aug 24 '17 at 8:39