【问题标题】:Given a word and a number for each letter of this word, how to create a full tree of every combinations?给定一个单词和该单词的每个字母的数字,如何创建每个组合的完整树?
【发布时间】:2019-04-16 08:20:47
【问题描述】:

假设我有“堆栈”这个词,它的每个字母都有一个数字,用于定义字母必须重复的次数。在 JSON 文件中,我将拥有以下内容:

{
   "s": 4,
   "t": 3,
   "a": 2,
   "c": 5,
   "k": 2
}

由此我想生成所有可能组合的完整树,即:

Depth 1: stack
Depth 2: stack, sstack, ssstack, sssstack
Depth 3: stack, sttack, stttack, sstack, ssttack, sstttack,ssstack, sssttack, ssstttack, sssstack, ssssttack, sssstttack
Depth 4: ... with 'a'
Depth 5: ... with 'c'
Depth 6: ... with 'k'

这将给出 4*3*2*5*2 = 240 种可能性。另外,我从几天前在这里问过的人那里获得了这些功能,并且我对其进行了一些修改:

def all_combinations(itr):
    lst = list(itr)
    for r in range(1, len(lst) + 1): 
        for perm in itertools.combinations(lst, r=r):
            yield perm 

def all_repeats(n, letters, word):
    for rep in all_combinations(letters):
        yield ''.join(char * n if char in rep else char for char in word)

这给了我:

word = 'stack'
for i in range(1,5):
    liste.append(''.join(list(all_repeats(i, ['s'], word))))

Output: ['stack', 'sstack', 'ssstack', 'sssstack']

据此,在给定 JSON 文件中的一对(字母、数字)的情况下,我如何递归调用此函数来创建所有可能性?

【问题讨论】:

  • 请注意,字典通常不被认为是“有序的”,因此您很容易以ackst 作为答案...将选项保存在列表列表中(即 [['s ',3],['t',3]]) 会更好地与常见语义对齐(@9​​87654326@ 确实存在,但使用更合适的数据类型通常更容易)
  • @SamMason 我不知道我的回答是否正确,但我似乎没有问题阅读 JSON 文件,即使我有重复的条目,我也可以设法删除它们。我想循环遍历 JSON 文件中的每个字母和数字,并给出一个我会做的列表“mylist”:mylist.append(''.join(list(all_repeats(number, letter, word))))

标签: python string list combinations


【解决方案1】:

几个版本,首先我们使用列表,因为它更容易索引

options = [
   ("s", 4),
   ("t", 3),
   ("a", 2),
   ("c", 5),
   ("k", 2),
]

现在我们可以获得一个长格式版本,以帮助了解发生了什么:

output = ['']

for letter, repeats in options:
    tmp = []
    for num in range(repeats):
        postfix = letter * (num+1)
        for cur in output:
            tmp.append(cur + postfix)
    output = tmp

如果你print(output),你会得到你所期望的。我建议在调试器中运行或插入大量 print 语句以了解发生了什么

作为第二个版本,我们可以使用 itertools 将其缩短为:

from itertools import product

tmp = [[l*(i+1) for i in range(num)] for l, num in options]
output = [''.join(l) for l in product(*tmp)]

您甚至可以将所有内容放在一行中,但在我看来它变得有点难以阅读

递归解决方案也很合适,但我会把它留给你

【讨论】:

    【解决方案2】:

    你也可以使用递归:

    data = {'s': 4, 't': 3, 'a': 2, 'c': 5, 'k': 2}
    def combos(d):
      yield ''.join(map(''.join, d))
      for i in data:
         if any(c[0] == i and len(c) < data[i] for c in d):
            yield from combos([c+[i] if c[0] == i and len(c) < data[i] else c for c in d])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多