如何生成一组字符的所有组合而不重复?

时间:2018-03-01 15:35:04

标签: python python-2.7

我有以下列表:

['a', 'b', 'c']

我正在寻找一种方法来生成包含这些字符的所有可能字符串,并具有以下限制:

  • 某个字符可能不会多次出现(aababaabca等无效)
  • 可能会排除某个字符(ab即使c不存在也有效; a即使bc不存在也有效本)

我可以用

[''.join(p) for p in permutations('abc')]

生成包含abc的所有字符串。不过我还要做

[''.join(p) for p in permutations('ab')]
[''.join(p) for p in permutations('ac')]
[''.join(p) for p in permutations('bc')]

正如您可以判断可用字符的初始列表是否很长我需要做很多工作。因此,我在Python中寻找一种优雅的方式来生成上述所有内容,只包含允许字符列表作为输入:

def generate(vals=['a', 'b', 'c']):
  # The initial list of allowed characters also has to be part of the 
  # final list since these also represent valid values
  res = vals
  # Generate all possible strings and store in res

  return res

我需要这个,因为我想为我的网络服务器的POST请求提供一个参数,其中一个参数(让我们称之为val)可以采用不同的唯一值(单个字符或一个那些组合)以触发一些数据生成。可用值列表会随着时间的推移而增长,因此,如果val的给定值是有效值,我希望通过自动检查来更轻松地处理请求。

我一直在考虑迭代允许字符列表中的每个元素并将其连接起来(' a'' ab',' ac',' abc',''' ba'' bc'等等)但我不知道如何那样做。

3 个答案:

答案 0 :(得分:2)

我会使用长度约束链接字符串字符的不同排列:

import itertools

def generate(vals="abc"):
    return ("".join(x) for x in itertools.chain.from_iterable(itertools.permutations(vals,i+1) for i in range(0,len(vals))))

print(list(generate("abc"))) # force iteration to print result

结果:

['a', 'b', 'c', 'ab', 'ac', 'ba', 'bc', 'ca', 'cb', 'abc', 'acb', 'bac', 'bca', 'cab', 'cba']

编辑:似乎我制作了一个powerset配方的变体(what's a good way to combinate through a set?),不考虑空字符串,考虑到字符的顺序(abccba是2个不同的项目并使用str.join直接生成字符串。

答案 1 :(得分:1)

您可以使用带有生成器表达式的递归:

def permutation(s, current = []):
   if len(current) == len(s):
      yield current
   else:
      yield current
      for i in s:
        if current.count(i) == 0:
            for h in permutation(s, current + [i]):
               yield h

print(map(''.join, list(permutation(['a', 'b', 'c']))[1:]))

输出:

['a', 'ab', 'abc', 'ac', 'acb', 'b', 'ba', 'bac', 'bc', 'bca', 'c', 'ca', 'cab', 'cb', 'cba']

答案 2 :(得分:1)

已经发布了正确答案,但我想试一试,尽可能让它变得可读。

from itertools import permutations as p

def gen(lst):
    y = [[a for a in p(lst,y)] for y in range(1,len(lst)+1)]

    this = []
    for i in y:
        while len(i)>0:
            this.append(i.pop())
    return [''.join(x) for x in this]

print(gen(['a','b','c']))