Reputation: 21
Need help creating a function that subsets a list. This is my code so far .
def substrings(txt):
"""Creates the sequence of all subsets as a list of text strings"""
for i in range(len(txt), len(txt) + 1):
for a in itertools.combinations( "a,b,c,d,e", 1):
yield functools.reduce(lambda i, a: i+a ,txt)
# Main program (does not change):
import functools, itertools
for sub in substrings('abcde'):
print(sub, end=' ')
The code should return
a b c d e ab ac ad ae bc bd be cd ce de abc abd abe acd ace ade bcd bce bde cde abcd abce abde acde bcde abcde
But I keep getting
abcde abcde abcde abcde abcde abcde abcde abcde abcde
Upvotes: 2
Views: 52
Reputation: 23079
A slick way to do this is, which doesn't require using any higher level modules, is using binary logic:
def substrings(inp):
for i in range(1, 2 ** len(inp)):
elem = ""
for j in range(len(inp)):
if ((1 << j) & i) > 0:
elem += inp[j]
yield elem
inp = ['a', 'b', 'c', 'd', 'e']
print([x for x in substrings(inp)])
Result:
['a', 'b', 'ab', 'c', 'ac', 'bc', 'abc', 'd', 'ad', 'bd', 'abd', 'cd', 'acd', 'bcd', 'abcd', 'e', 'ae', 'be', 'abe', 'ce', 'ace', 'bce', 'abce', 'de', 'ade', 'bde', 'abde', 'cde', 'acde', 'bcde', 'abcde']
Here, we iterate over all of the numbers between 1 and 2 raised to the length of the input list. This produces a bitfield, where every combination of bits represents a different combination of the input strings in the list. For example, the last number, 2**<len>
, is a number that has a 1
in every bit position, representing the set with all input elements included.
Upvotes: 1
Reputation: 780879
txt
.itertools.combinations()
should be txt
, not a hard-coded string (which also shouldn't contain ,
), and the combination size should be i
, not 1.''.join()
to convert the combination to a string, not functools.reduce()
. And if you do use reduce()
, the argument should be a
, not txt
. That's why you keep getting the whole string, not the subsets.In general, if you have a for
loop and never use the iteration variable, something is usually wrong.
# Main program (does not change):
import itertools
def substrings(txt):
"""Creates the sequence of all subsets as a list of text strings"""
for i in range(1, len(txt) + 1):
for a in itertools.combinations(txt, i):
yield ''.join(a)
for sub in substrings('abcde'):
print(sub, end=' ')
Upvotes: 1
Reputation: 59184
Your range is incorrect, and also you seem to have hardcoded the input (abcde
) in your function instead of using txt
. Try this:
def substrings(txt):
"""Creates the sequence of all subsets as a list of text strings"""
for i in range(1, len(txt) + 1):
for a in itertools.combinations(txt, i):
yield "".join(a)
Upvotes: 1