Reputation: 867
I currently have a list of choices:
a = ['D1',
'C1',
'D2',
'C2',
'D3',
'C3',
'D4',
'C4',
'D5',
'C5',]
I want a new list with nested lists inside of possible combinations. Like this:
b = [
'D1',
'C1',
'D2',
'C2',
'D3',
'C3',
'D4',
'C4',
'D5',
'C5',
['D1', 'C1'],
['D1', 'D2'],
['D1', 'C2']
.
.
['D1', 'C1', 'D2']
.
.
['D1', 'C1', 'D2', 'C2']
.
.
['D1', 'C1', 'D2', 'C2', 'D3']
:
etc
Upvotes: 1
Views: 571
Reputation: 123473
You can create a new list using itertools.combinations
in conjunction with a very efficient and relatively succinct construct called a list comprehension. However for doing this it got a little complicated partially by the fact that not all of the items in the final list are themselves not nested lists. I actually suspect having it that way will make it harder for you to process the list later on, but, regardless, here's the simplest implementation I've been able to devise which produces exactly the list you said you wanted:
from itertools import combinations
a = ['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5']
b = [item for sublist in (list(combo[0] if len(combo) < 2 else list(combo)
for combo in combinations(a, n))
for n in range(1, len(a)+1)) for item in sublist]
from pprint import pprint # print the result
print 'b = \\'
pprint(b[:14] + ['... lines omitted ...'] + b[-14:])
Output:
b = \
['D1',
'C1',
'D2',
'C2',
'D3',
'C3',
'D4',
'C4',
'D5',
'C5',
['D1', 'C1'],
['D1', 'D2'],
['D1', 'C2'],
['D1', 'D3'],
'... lines omitted ...',
['C1', 'D2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
['C1', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
['D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5'],
['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'C5'],
['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'D5', 'C5'],
['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'C4', 'D5', 'C5'],
['D1', 'C1', 'D2', 'C2', 'D3', 'D4', 'C4', 'D5', 'C5'],
['D1', 'C1', 'D2', 'C2', 'C3', 'D4', 'C4', 'D5', 'C5'],
['D1', 'C1', 'D2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
['D1', 'C1', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
['D1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
['C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5']]
Upvotes: 2
Reputation: 58271
You need actually power set of a
here is my solution:
def powerset(seq):
"""
Returns all the subsets of this set. This is a generator.
"""
if len(seq) <= 1:
yield seq
yield []
else:
for item in powerset(seq[1:]):
yield [seq[0]]+item
yield item
a =['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5']
b = [x for x in powerset(a)]
b.sort(key = len)
for x in b:
print x
my refrence site: And Its working you can see at codepade here
EDIT a instance of run.
a =['D1', 'C1', 'D2']
b = [x for x in powerset(a)]
b.sort(key = len)
for x in b:
print x
And its output:
[]
['D2']
['C1']
['D1']
['C1', 'D2']
['D1', 'D2']
['D1', 'C1']
['D1', 'C1', 'D2']
You can find Better code for Powerset in Python from following links.
http://docs.python.org/2/library/itertools.html
http://mail.python.org/pipermail/tutor/2004-April/029413.html
http://ruslanspivak.com/2011/06/09/power-set-generation-a-joy-of-python/
Although Mr.martineau given small and fast code but I don't understand itertools yet.
Upvotes: 2
Reputation: 17532
I suggest using itertools.permutations(a)
.
import itertools
a = ['D1',
'C1',
'D2',
'C2',
'D3',
'C3',
'D4',
'C4',
'D5',
'C5',]
b = list(itertools.permutations(a)) # this gives permutations of the same length
If you want ALL the possible permutations (of varying lengths), you can use a for
loop:
b = []
for i in range(1, len(a)+1):
b.extend(list(itertools.permutations(a, i)))
Put that into a list comprehension:
b = [list(itertools.permutations(x, i)) for i in range(1, len(x)+1)]
Upvotes: 1
Reputation: 34282
Check out itertools.combinations
:
b = []
for len_ in xrange(len(a)):
b.extend(itertools.combinations(a, len_+1)
See also the powerset recipe from the itertools docs:
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
Upvotes: 2