Home > database >  Creates a sequence of all subsets as a list of text strings
Creates a sequence of all subsets as a list of text strings

Time:12-16

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

Thanks in advanced.

CodePudding user response:

  • You should be looping from 1 to the length of txt.
  • The argument to itertools.combinations() should be txt, not a hard-coded string (which also shouldn't contain ,), and the combination size should be i, not 1.
  • Use ''.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=' ')

CodePudding user response:

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)

CodePudding user response:

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 two 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.

  • Related