【问题标题】:With variable length list of variable length strings, how do I create all combinations使用可变长度字符串的可变长度列表,如何创建所有组合
【发布时间】:2014-12-16 18:55:26
【问题描述】:

在 python 3 中,我有一个可变长度列表,其中列表的每个元素都是一个可变长度字符串。像这样的

['TO', 'G', 'ZDO', 'DEO', 'SGT', 'D', 'Z', 'FT', 'OV']

我想遍历每个可能的单词组合,其中组成单词的字母来自列表中的字符串,并且单词的长度与列表的长度相同。所以像这样的

TGZDSDZFO
TGZDSDZFV
TGZDSDZTO
...
OGOOTDZTO
OGOOTDZTV

我无法为 n 大小的列表提出通用解决方案。

【问题讨论】:

  • 你怎么知道要为列表中的每个字符串提取多少个字符
  • 时间,我希望每个字符串一次一个字符。列表中的每个字符串都包含在单词中该位置构成单词的可能字符。

标签: python string combinations


【解决方案1】:
>>> (''.join(s) for s in itertools.product(*['TO', 'G', 'ZDO', 'DEO', 'SGT', 'D', 'Z', 'FT', 'OV']))
<generator object <genexpr> at 0x7f2a46468f00>
>>> # to demonstrate:
... 
>>> list(itertools.islice((''.join(s) for s in itertools.product(*['TO', 'G', 'ZDO', 'DEO', 'SGT', 'D', 'Z', 'FT', 'OV'])), 3))
['TGZDSDZFO', 'TGZDSDZFV', 'TGZDSDZTO']

【讨论】:

  • itertools.product() 是所有参数的乘积。 * 将列表分隔为函数调用的单独参数。 ''.join() 不带分隔符连接。其余的只是一个正常的基因。
【解决方案2】:

正如其他人所建议的那样,itertools 可能是解决此问题的最简单/最容易的方法。但是,如果您希望编写自己的算法(即重新实现 itertools 在后台所做的工作),请查看以下内容:

def allPerms(L, sofar=''):
    if not L:
        print(sofar)
    else:
        for char in L[0]:
            allPerms(L[1:], sofar+char)

输出:

In [97]: L = ['TO', 'G', 'ZDO', 'DEO', 'SGT', 'D', 'Z', 'FT', 'OV']

In [98]: allPerms(L)
TGZDSDZFO
TGZDSDZFV
TGZDSDZTO
TGZDSDZTV
TGZDGDZFO
TGZDGDZFV
TGZDGDZTO
TGZDGDZTV
TGZDTDZFO
TGZDTDZFV
TGZDTDZTO
TGZDTDZTV
TGZESDZFO
TGZESDZFV
TGZESDZTO
TGZESDZTV
TGZEGDZFO
TGZEGDZFV
TGZEGDZTO
TGZEGDZTV
--- truncated ---

编辑

As @njzk2 points out,python3 的 yield-from 在使输出可用方面做得非常出色:

def allPerms(L, sofar=''):
    if not L: yield sofar
    else:
        for char in L[0]: yield from allPerms(L[1:], sofar+char)

输出:

In [118]: for i in allPerms(L): print(i)
TGZDSDZFO
TGZDSDZFV
TGZDSDZTO
TGZDSDZTV
TGZDGDZFO
TGZDGDZFV
TGZDGDZTO
TGZDGDZTV
TGZDTDZFO
TGZDTDZFV
TGZDTDZTO
TGZDTDZTV
TGZESDZFO
TGZESDZFV
TGZESDZTO
TGZESDZTV
TGZEGDZFO
TGZEGDZFV
TGZEGDZTO
TGZEGDZTV
TGZETDZFO
TGZETDZFV
TGZETDZTO
--- truncated ---

【讨论】:

  • yield 会比print 更好,因为它允许使用输出。
  • 我也在尝试,到目前为止还没有运气。我到了会通知你的。
  • 这个stackoverflow.com/a/6755918/671543解释说在python 3之前,我们需要重新迭代来传递yield,但是在python 3中我们可以使用yield from,它会依次生成所有项目。 python2 -> yield sofar + for value in allPerms(L[1:], sofar+char): yield value, python3 -> yield sofar + yield from allPerms(L[1:], sofar+char)
【解决方案3】:

您可以使用itertools 模块来创建所需长度的排列。 将所有工作组合成一个字符串并在排列函数中使用它

lst = ['TO', 'G', 'ZDO', 'DEO', 'SGT', 'D', 'Z', 'FT', 'OV']
length = len(lst)

combined = ''.join(lst)
all_perms = itertools.permutations(combined, length)
#this will give you something like [('T', 'O', ...), (...),]

print ([''.join(x) for x in all_perms])

【讨论】:

  • 我认为permutations 在这里不合适
  • 请解释原因
  • 你运行了这段代码吗?您是否将输出与 OP 请求的输出进行了比较?
  • @CCKx 因为它没有产生预期的输出,对于初学者来说。
  • @njzk2,同意。我没有阅读 OP 对 Tim Castelijns 评论的回复。 itertools.product 更有意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-15
  • 2014-05-28
  • 2012-02-24
  • 1970-01-01
  • 2015-02-26
  • 1970-01-01
相关资源
最近更新 更多