Python 联接字符串以生成字符串中所有单词的组合
Python Join String to Produce Combinations For All Words in String
如果我的字符串是这样的:'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
在输出中。
最简单的就是递归地做。
- 终止条件:单元素列表的薛定谔连接就是那个词。
- 循环条件:假设 L 是除第一个单词之外的所有单词的薛定谔连接。然后列表的 Schrödinger 连接包含来自 L 的所有元素,第一个单词直接放在前面,以及来自 L 的所有元素,第一个单词前面加上中间 space.
(假设您不小心遗漏了 thisis astring
。如果是故意的,我肯定不知道问题是什么 :P )
另一种非递归的方法是枚举从 0
到 2^(number of words - 1) - 1
的所有数字,然后使用每个数字的二进制表示作为选择器,无论是否 space 需要存在。所以,比如上面提到的thisis astring
对应0b010
,对于"nospace, space, nospace".
好吧,我花了比预期更长的时间...这实际上比我想象的要复杂 :)
主要思想:
拆分字符串时space的个数就是长度或者拆分后的数组-1,我们的例子中有3个space:
'this is a string'
^ ^ ^
我们将采用 二进制表示 have/not 的所有选项都具有 space 之一,所以在我们的例子中它'将是:
000
001
011
100
101
...
并且对于每个选项,我们将分别 generate
句子,其中 111 代表所有 3 space:'this is a string' 和 000 代表完全没有-space : '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 想到了同样的想法 - 比我想得更快的荣誉!伟大的思想是相似的 ;)
你也可以使用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])
使用 itertools 产品的更简单(比公认答案快 3 倍)的方法:
s = 'this is a string'
s2 = s.replace('%', '%%').replace(' ', '%s')
for i in itertools.product((' ', ''), repeat=s.count(' ')):
print(s2 % i)
如果我的字符串是这样的:'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
在输出中。
最简单的就是递归地做。
- 终止条件:单元素列表的薛定谔连接就是那个词。
- 循环条件:假设 L 是除第一个单词之外的所有单词的薛定谔连接。然后列表的 Schrödinger 连接包含来自 L 的所有元素,第一个单词直接放在前面,以及来自 L 的所有元素,第一个单词前面加上中间 space.
(假设您不小心遗漏了 thisis astring
。如果是故意的,我肯定不知道问题是什么 :P )
另一种非递归的方法是枚举从 0
到 2^(number of words - 1) - 1
的所有数字,然后使用每个数字的二进制表示作为选择器,无论是否 space 需要存在。所以,比如上面提到的thisis astring
对应0b010
,对于"nospace, space, nospace".
好吧,我花了比预期更长的时间...这实际上比我想象的要复杂 :)
主要思想:
拆分字符串时space的个数就是长度或者拆分后的数组-1,我们的例子中有3个space:
'this is a string'
^ ^ ^
我们将采用 二进制表示 have/not 的所有选项都具有 space 之一,所以在我们的例子中它'将是:
000
001
011
100
101
...
并且对于每个选项,我们将分别 generate
句子,其中 111 代表所有 3 space:'this is a string' 和 000 代表完全没有-space : '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 想到了同样的想法 - 比我想得更快的荣誉!伟大的思想是相似的 ;)
你也可以使用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])
使用 itertools 产品的更简单(比公认答案快 3 倍)的方法:
s = 'this is a string'
s2 = s.replace('%', '%%').replace(' ', '%s')
for i in itertools.product((' ', ''), repeat=s.count(' ')):
print(s2 % i)