Reputation: 2763
Confession: this is for a class.
I am trying to generate all subsets of length 1 - length(full set), but they must be in order.
So, with an input of (4,2), valid results would be (4), (4,2), and (2). Would not be (4,4) (2,2) or (2,4)
eta (4,2,2) should return (2,2) as well.
Length is not pre-determined.
What I have right now:
def gen_all_partials(outcomes, length):
"""
Iterative function that enumerates the set of all sequences of
outcomes of lengths up to given length.
"""
answer_set = set([()])
for dummy_idx in range(length):
temp_set = set()
for partial_sequence in answer_set:
for item in outcomes:
new_sequence = list(partial_sequence)
new_sequence.append(item)
temp_set.add(tuple(new_sequence))
answer_set = temp_set
return answer_set
This is partially obtained by a given function. I don't understand how Python is iterating over an empty set in that 2nd "for" loop. This current code outputs (4,4), (2,2), and (2,4) in addition to the "right" answers.
I'm getting hung up on the nested loops and keeping track of multiple counters and having different lengths for the desired output.
I have also tried this:
def gen_all_partials(outcomes, length):
"""
Iterative function that enumerates the set of all sequences of
outcomes of lengths up to given length.
"""
answer_set = set([()])
for dummy_idx in range(length):
temp_set = set()
for partial_sequence in answer_set:
for item in outcomes:
new_sequence = list(partial_sequence)
new_sequence.append(item)
if new_sequence not in temp_set:
temp_outcomes = list(outcomes[:])
add_to_set = True
for val in new_sequence:
if val in temp_outcomes:
order_list = []
for dummy_bit in val:
order_list.append(val.index(dummy_bit))
if order_list == order_list.sort():
temp_outcomes.remove(val)
else:
add_to_set = False
else:
add_to_set = False
if add_to_set:
temp_set.add(tuple(new_sequence))
answer_set = temp_set
return answer_set
Upvotes: 2
Views: 220
Reputation: 121987
From the ever-helpful itertools
recipes:
from itertools import chain, combinations
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))
This includes the empty set, but you can trivially alter the range
to handle that.
Upvotes: 3
Reputation: 42597
Here's one way, using recursion, though you can alternatively do it iteratively with a loop, and join the lists for each n
:
a = [4,2]
def subseqs(x):
def go(x, n):
return zip(*(x[i:] for i in range(n))) + go(x, n-1) if n else []
return go(x, len(x))
print subseqs(a) # [(4, 2), (4,), (2,)]
or using a list comprehension:
print sum([zip(*(a[i:] for i in range(n))) for n in range(len(a)+1)], [])
Upvotes: 2