python – How to get all possible combinations of a list’s elements?
python – How to get all possible combinations of a list’s elements?
This answer missed one aspect: the OP asked for ALL combinations… not just combinations of length r.
So youd either have to loop through all lengths L:
import itertools
stuff = [1, 2, 3]
for L in range(0, len(stuff)+1):
for subset in itertools.combinations(stuff, L):
print(subset)
Or — if you want to get snazzy (or bend the brain of whoever reads your code after you) — you can generate the chain of combinations() generators, and iterate through that:
from itertools import chain, combinations
def all_subsets(ss):
return chain(*map(lambda x: combinations(ss, x), range(0, len(ss)+1)))
for subset in all_subsets(stuff):
print(subset)
Have a look at itertools.combinations:
itertools.combinations(iterable, r)
Return r length subsequences of elements from
the input iterable.Combinations are emitted in lexicographic sort order. So, if the
input iterable is sorted, the
combination tuples will be produced in
sorted order.
Since 2.6, batteries are included!
python – How to get all possible combinations of a list’s elements?
Heres a lazy one-liner, also using itertools:
from itertools import compress, product
def combinations(items):
return ( set(compress(items,mask)) for mask in product(*[[0,1]]*len(items)) )
# alternative: ...in product([0,1], repeat=len(items)) )
Main idea behind this answer: there are 2^N combinations — same as the number of binary strings of length N. For each binary string, you pick all elements corresponding to a 1.
items=abc * mask=###
|
V
000 ->
001 -> c
010 -> b
011 -> bc
100 -> a
101 -> a c
110 -> ab
111 -> abc
Things to consider:
- This requires that you can call
len(...)
onitems
(workaround: ifitems
is something like an iterable like a generator, turn it into a list first withitems=list(_itemsArg)
) - This requires that the order of iteration on
items
is not random (workaround: dont be insane) - This requires that the items are unique, or else
{2,2,1}
and{2,1,1}
will both collapse to{2,1}
(workaround: usecollections.Counter
as a drop-in replacement forset
; its basically a multiset… though you may need to later usetuple(sorted(Counter(...).elements()))
if you need it to be hashable)
Demo
>>> list(combinations(range(4)))
[set(), {3}, {2}, {2, 3}, {1}, {1, 3}, {1, 2}, {1, 2, 3}, {0}, {0, 3}, {0, 2}, {0, 2, 3}, {0, 1}, {0, 1, 3}, {0, 1, 2}, {0, 1, 2, 3}]
>>> list(combinations(abcd))
[set(), {d}, {c}, {c, d}, {b}, {b, d}, {c, b}, {c, b, d}, {a}, {a, d}, {a, c}, {a, c, d}, {a, b}, {a, b, d}, {a, c, b}, {a, c, b, d}]