简体   繁体   中英

List all possible words with n letters

I want to list all possible words with n letters where the first letter can be a1 or a2, the second can be b1, b2 or b3, the third can be c1 or c2, ... Here's a simple example input-output for n=2 with each letter having 2 alternatives:

  • input = [["a","b"],["c","d"]]
  • output = ["ac", "ad", "bc", "bd"]

I tried doing this recursively by creating all possible words with the first 2 letters first, so something like this:

def go(l):
    if len(l) > 2:
        head = go(l[0:2])
        tail = l[2:]
        tail.insert(0, head)
        go(tail)
    elif len(l) == 2:
        res = []
        for i in l[0]:
            for j in l[1]:
                res.append(i+j)
        return res
    elif len(l) == 1:
        return l
    else:
        return None

However, this becomes incredibly slow for large n or many alternatives per letter. What would be a more efficient way to solve this?

Thanks

I think you just want itertools.product here:

>>> from itertools import product
>>> lst = ['ab', 'c', 'de']
>>> words = product(*lst)
>>> list(words)
[('a', 'c', 'd'), ('a', 'c', 'e'), ('b', 'c', 'd'), ('b', 'c', 'e')]`

Or, if you wanted them joined into words:

>>> [''.join(word) for word in product(*lst)]
['acd', 'ace', 'bcd', 'bce']

Or, with your example:

>>> lst = [["a","b"],["c","d"]]
>>> [''.join(word) for word in product(*lst)]
['ac', 'ad', 'bc', 'bd']

Of course for very large n or very large sets of letters (size m ), this will be slow. If you want to generate an exponentially large set of outputs ( O(m**n) ), that will take exponential time. But at least it has constant rather than exponential space (it generates one product at a time, instead of a giant list of all of them), and will be faster than what you were on your way to by a decent constant factor, and it's a whole lot simpler and harder to get wrong.

You can use the permutations from the built-in itertools module to achieve this, like so

>>> from itertools import permutations
>>> [''.join(word) for word in permutations('abc', 2)]
['ab', 'ac', 'ba', 'bc', 'ca', 'cb']

Generating all strings of some length with given alphabet :

test.py :

def generate_random_list(alphabet, length):
    if length == 0: return []
    c = [[a] for a in alphabet[:]]
    if length == 1: return c
    c = [[x,y] for x in alphabet for y in alphabet]
    if length == 2: return c
    for l in range(2, length):
        c = [[x]+y for x in alphabet for y in c]
    return c

if __name__ == "__main__":
    for p in generate_random_list(['h','i'],2):
        print p

$ python2 test.py

['h', 'h']
['h', 'i']
['i', 'h']
['i', 'i']

Next Way :

def generate_random_list(alphabet, length):
    c = []
    for i in range(length):
        c = [[x]+y for x in alphabet for y in c or [[]]]
    return c

if __name__ == "__main__":
    for p in generate_random_list(['h','i'],2):
        print p

Next Way :

import itertools
if __name__ == "__main__":
    chars = "hi"
    count = 2
    for item in itertools.product(chars, repeat=count):
        print("".join(item))

import itertools
print([''.join(x) for x in itertools.product('hi',repeat=2)])

Next Way :

from itertools import product
#from string import ascii_letters, digits

#for i in product(ascii_letters + digits, repeat=2):
for i in product("hi",repeat=2):
    print(''.join(i))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM