Search code examples
pythonstringalphabet

Understanding and simplifying this line


I found this example for finding all strings of an alphabet of a given length.

for i in range(length):
    result = [str(x)+str(y) for x in alphabet for y in result or ['']]

I'm trying to understand how this works and if this was implemented with for loops, how it would look - all my attempts at simplifying it become very messy and crash with infinite loops... while this one works every time.


Example:

def allstrings(alphabet, length):
    """Find the list of all strings of 'alphabet' of length 'length'"""

    alphabet = list(alphabet)

    result = []

    for i in range(length):
        result = [str(x)+str(y) for x in alphabet for y in result or ['']]

    return result

# will return ['aa', 'ab', 'ba', 'bb']
print(allstrings({'a', 'b'}, 2)))

# will return ['000', '001', '010', '011', '100', '101', '110', '111']
print(allstrings({'0', '1'}, 4)))

Code is modified from: http://code.activestate.com/recipes/425303-generating-all-strings-of-some-length-of-a-given-a/


Solution

  • In short this is equivalent of your code, since I haven't seen others provide you with it. I do recommend the use of itertools like Joran Beasley wrote because they're faster, and they also make a clear and simpler statement.

    def permute(alphabet):
        result = []
        for x in alphabet:
            for y in alphabet:
                result.append(str(x)+str(y))
        return result
    

    With ouptut in IDLE as:

    >>> alphabet = ["a", "b", "c"]
    >>> r = permute(alphabet)
    >>> r
    ['aa', 'ab', 'ac', 'ba', 'bb', 'bc', 'ca', 'cb', 'cc']
    

    However this approach makes it harder to define the desired length. To achieve that effect you would have to do something like:

    def permute(original, permutated):
        result = []
        for x in alphabet:
            for y in permutated or [""]:
                result.append(str(x)+str(y))
        return result
    
    def helper(alphabet, length):
        res = []
        for i in range(length):
            res = permute(alphabet, res)
        return res
    

    Output of which now looks like:

    >>> h = helper(alphabet, 2)
    >>> h
    ['aa', 'ab', 'ac', 'ba', 'bb', 'bc', 'ca', 'cb', 'cc']
    >>> h = helper(alphabet, 3)
    >>> h
    ['aaa', 'aab', 'aac', 'aba', 'abb', 'abc', 'aca', 'acb', 'acc', 'baa', 'bab', 'bac', 'bba', 'bbb', 'bbc', 'bca', 'bcb', 'bcc', 'caa', 'cab', 'cac', 'cba', 'cbb', 'cbc', 'cca', 'ccb', 'ccc']
    

    Can you make out what's happening? Or should I write up an explanation. (but please make an effort first).