【问题标题】:Python Join String to Produce Combinations For All Words in StringPython 连接字符串以生成字符串中所有单词的组合
【发布时间】:2015-04-20 03:46:25
【问题描述】:

如果我的字符串是这样的:'this is a string',我如何通过将每个单词与其相邻单词连接来产生所有可能的组合?

这个输出会是什么样子:

this is a string
thisis a string
thisisa string
thisisastring
thisis astring
this isa string
this isastring
this is astring

我尝试过的:

s = 'this is a string'.split()    
for i, l in enumerate(s):
        ''.join(s[0:i])+' '.join(s[i:])

这会产生:

'this is a string'
'thisis a string'
'thisisa string'
'thisisastring'

我意识到我需要更改 s[0:i] 部分,因为它静态锚定在 0,但我不知道如何移动到下一个单词 is,同时仍然在输出中包含 this

【问题讨论】:

    标签: string python-3.x join combinations


    【解决方案1】:

    使用 itertools 产品的更简单(比公认答案快 3 倍)的方法:

    s = 'this is a string'
    s2 = s.replace('%', '%%').replace(' ', '%s')
    for i in itertools.product((' ', ''), repeat=s.count(' ')):
        print(s2 % i)
    

    【讨论】:

    • 非常酷!我投了赞成票。我不明白这部分虽然.replace('%', '%%')。这对我来说似乎是多余的。
    • @tommy.carstensen - 如果它们恰好在原始字符串中,则转义 % 字符以准备进一步的格式操作
    【解决方案2】:

    你也可以使用itertools.product():

    import itertools
    
    s = 'this is a string'
    
    words = s.split()
    for t in itertools.product(range(len('01')), repeat=len(words)-1):
        print(''.join([words[i]+t[i]*' ' for i in range(len(t))])+words[-1])
    

    【讨论】:

    • 请参阅@panda-34 提供的更快解决方案。
    【解决方案3】:

    嗯,我花了比我预期更长的时间......这实际上比我想象的要复杂:)

    主要思想:

    分割字符串时的空格数是长度或分割数组 - 1。在我们的例子中有3个空格:

    'this is a string'
         ^  ^ ^
    

    我们将采用所有选项的二进制表示,以包含/不包含任何一个空格,因此在我们的例子中它将是:

    000
    001
    011
    100
    101
    ...
    

    对于每个选项,我们将分别generate 句子,其中 111 表示所有 3 个空格:“这是一个字符串”,000 表示根本没有空格:“thisisastring”

    def binaries(n):
        res = []
        for x in range(n ** 2 - 1):
            tmp = bin(x)
            res.append(tmp.replace('0b', '').zfill(n))
        return res
    
    
    def generate(arr, bins):
        res = []
        for bin in bins:
            tmp = arr[0]
            i = 1
            for digit in list(bin):
                if digit == '1':
                    tmp = tmp + " " + arr[i]
                else:
                    tmp = tmp + arr[i]
                i += 1
            res.append(tmp)
        return res
    
    
    def combinations(string):
        s = string.split(' ')
        bins = binaries(len(s) - 1)
        res = generate(s, bins)
        return res
    
    
    print combinations('this is a string')
    # ['thisisastring', 'thisisa string', 'thisis astring', 'thisis a string', 'this isastring', 'this isa string', 'this is astring', 'this is a string']
    

    更新:
    我现在看到 Amadan 也想到了同样的想法——因为比我想得更快而受到赞誉!伟大的思想都一样;)

    【讨论】:

      【解决方案4】:

      最简单的就是递归。

      • 终止条件:单个元素列表的薛定谔连接就是那个词。
      • 循环条件:假设 L 是除第一个之外的所有单词的薛定谔连接。然后列表的薛定谔连接由 L 中的所有元素组成,第一个单词直接前置,L 中的所有元素第一个单词前置,中间有空格。

      (假设您不小心错过了thisis astring。如果是故意的,我敢肯定我不知道问题是什么:P)

      另一种非递归方式是枚举从02^(number of words - 1) - 1 的所有数字,然后使用每个数字的二进制表示作为选择器,无论是否需要存在空格。所以,比如上面提到的thisis astring对应0b010,代表“nospace, space, nospace”。

      【讨论】:

      • 你说得对,我确实错过了thisis astring。谢谢你的收获。我用这个更正更新了我的问题。我会花一些时间来了解如何应用你的 cmets Amadan。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-17
      • 1970-01-01
      • 2021-12-03
      • 2020-08-18
      • 1970-01-01
      相关资源
      最近更新 更多