如何生成字符之间带有空格的字符串的所有可能组合? Python
Posted
技术标签:
【中文标题】如何生成字符之间带有空格的字符串的所有可能组合? Python【英文标题】:How do I generate all possible combinations of a string with spaces between the characters? Python 【发布时间】:2013-05-04 22:24:12 【问题描述】:如何生成字符之间带有空格的字符串的所有可能组合?
[in]: "foobar"
[out]:
['foobar', 'f oobar', 'fo obar', 'f o obar', 'foo bar', 'f oo bar', 'fo o bar',
'f o o bar', 'foob ar', 'f oob ar', 'fo ob ar', 'f o ob ar', 'foo b ar',
'f oo b ar', 'fo o b ar', 'f o o b ar', 'fooba r', 'f ooba r', 'fo oba r',
'f o oba r', 'foo ba r', 'f oo ba r', 'fo o ba r', 'f o o ba r', 'foob a r',
'f oob a r', 'fo ob a r', 'f o ob a r', 'foo b a r', 'f oo b a r', 'fo o b a r',
'f o o b a r', 'foobar', 'f oobar', 'fo obar', 'f o obar', 'foo bar',
'f oo bar', 'fo o bar', 'f o o bar', 'foob ar', 'f oob ar', 'fo ob ar',
'f o ob ar', 'foo b ar', 'f oo b ar', 'fo o b ar', 'f o o b ar', 'fooba r',
'f ooba r', 'fo oba r', 'f o oba r', 'foo ba r', 'f oo ba r', 'fo o ba r',
'f o o ba r', 'foob a r', 'f oob a r', 'fo ob a r', 'f o ob a r', 'foo b a r',
'f oo b a r', 'fo o b a r', 'f o o b a r']
【问题讨论】:
提示:你可以考虑在每个位置拆分一个字符串,然后递归地对每个子字符串做同样的事情 你的输出怎么变化这么大? 【参考方案1】:import itertools as it
def func(s):
if not s:
return [s]
binary = it.product(['',' '], repeat=len(s)-1)
zipped = (it.izip_longest(s , comb, fillvalue='') for comb in binary)
return [''.join(it.chain.from_iterable(x)) for x in zipped]
func('foobar')
输出:
['foobar',
'fooba r',
'foob ar',
'foob a r',
'foo bar',
'foo ba r',
'foo b ar',
'foo b a r',
'fo obar',
'fo oba r',
'fo ob ar',
'fo ob a r',
'fo o bar',
'fo o ba r',
'fo o b ar',
'fo o b a r',
'f oobar',
'f ooba r',
'f oob ar',
'f oob a r',
'f oo bar',
'f oo ba r',
'f oo b ar',
'f oo b a r',
'f o obar',
'f o oba r',
'f o ob ar',
'f o ob a r',
'f o o bar',
'f o o ba r',
'f o o b ar',
'f o o b a r']
【讨论】:
@jamylak -- 不,它没有。 你有 32 种组合,而不是 OP 的 64 种。而且你的组合是倒退的。for x in product(('', ' '), repeat=len(text)):
L.append(''.join(chain.from_iterable(izip(text, reversed(x)))).rstrip())
之类的东西应该可以修复它
@jamylak - 它确实提供了所有可能的组合 - 但不是重复的。 set(myres) == set(OPres)
:)
您可以添加if not s: return [s]
以支持空字符串。 @jamylak:It is easy to see that the solution is correct by replacing ['', ' ']
with "01"
and counting in binary (2) base from 0 to 2**(len(s)-1) - 1
(注意:-1
在权力中,因为要获得 3 次绳索,我们只需要 2 次切割)。【参考方案2】:
from itertools import product
text = "foobar"
L = [''.join(reversed(x)).rstrip()
for x in product(*[(c, c+' ') for c in reversed(text)])]
print L
['foobar', 'f oobar', 'fo obar', 'f o obar', 'foo bar', 'f oo bar', 'fo o bar', 'f o o bar', 'foob ar', 'f oob ar', 'fo ob ar', 'f o ob ar', 'foo b ar', 'f oo b ar', 'fo o b ar', 'f o o b ar', 'fooba r', 'f ooba r', 'fo oba r', 'f o oba r', 'foo ba r', 'f oo ba r', 'fo o ba r', 'f o o ba r', 'foob a r', 'f oob a r', 'fo ob a r', 'f o ob a r', 'foo b a r', 'f oo b a r', 'fo o b a r', 'f o o b a r', 'foobar', 'f oobar', 'fo obar', 'f o obar', 'foo bar', 'f oo bar', 'fo o bar', 'f o o bar', 'foob ar', 'f oob ar', 'fo ob ar', 'f o ob ar', 'foo b ar', 'f oo b ar', 'fo o b ar', 'f o o b ar', 'fooba r', 'f ooba r', 'fo oba r', 'f o oba r', 'foo ba r', 'f oo ba r', 'fo o ba r', 'f o o ba r', 'foob a r', 'f oob a r', 'fo ob a r', 'f o ob a r', 'foo b a r', 'f oo b a r', 'fo o b a r', 'f o o b a r']
【讨论】:
非常优雅。我从没想过这样使用product
和reversed
=)【参考方案3】:
这是我上面递归想法的一个实现:
def string_spaces(s):
ret = set([s]) # use a set rather than a list to prevent duplicates
for i in range(1, len(s)):
for fst in string_spaces(s[:i]):
for snd in string_spaces(s[i:]):
ret.add(fst + ' ' + snd)
return ret
例子:
In [11]: string_spaces('foo')
Out[11]: set(['foo', 'f o o', 'f oo', 'fo o'])
注意:Python 有 1000 个堆栈帧的递归限制,因此对于非常长的字符串(超过 1000 个字符)会崩溃。
【讨论】:
【参考方案4】:这可能不是最有效的方法,但我会列出两个列表。一个有一个字母作为每个元素,另一个有每个字母后跟一个空格。 (每次都跳过最后一个字母,因为它总是没有空格。)通过在每个字母的两个列表之间进行选择来生成可能的间距(可以建模为二进制数,其中 0 = 没有空格,1 = 空格)
def spacify(word):
no_space = list(word[:-1])
spaced = [lt + ' ' for lt in no_space]
for i in range(2 ** (len(word) - 1)):
spaced_word = ""
for j in range(len(word) - 1):
if i % 2 == 0:
spaced_word += no_space[j]
else:
spaced_word += spaced[j]
i = i // 2 # Or use bit shifting to be fancy
print spaced_word + word[-1]
【讨论】:
不是通用解决方案。都不是高效的。 其实你只需要上到2 ** 4(16个组合),因为你要去掉单词的首尾字母。 解决方案并不完全正确,因为最后一个字母后面不应该有空格。这也减少了可能性的数量。立即修复。 其实真的不正确。这会生成添加空格的所有可能方法,但问题实际上并不要求这样做。例如,fo ob ar
未作为示例列出。
@Titandrake 我认为 OP 也想要这些。但错过了提供的示例中的那些。【参考方案5】:
from itertools import combinations
def gen_spaces(data):
return_value = []
size = len(data)-1
for num_spaces in range(size):
for comb in combinations(range(size), num_spaces+1):
data_as_list = list(data)
for i in comb:
data_as_list[i] +=' '
return_value.append(''.join(data_as_list))
return return_value
from pprint import pprint
pprint(gen_spaces("foobar"))
输出:
['f oobar',
'fo obar',
'foo bar',
'foob ar',
'fooba r',
'f o obar',
'f oo bar',
'f oob ar',
'f ooba r',
'fo o bar',
'fo ob ar',
'fo oba r',
'foo b ar',
'foo ba r',
'foob a r',
'f o o bar',
'f o ob ar',
'f o oba r',
'f oo b ar',
'f oo ba r',
'f oob a r',
'fo o b ar',
'fo o ba r',
'fo ob a r',
'foo b a r',
'f o o b ar',
'f o o ba r',
'f o ob a r',
'f oo b a r',
'fo o b a r',
'f o o b a r']
更新:
您提到您需要“字符串与字符之间的空格的所有可能组合”,但同时您在[Out]
中提供的示例并未反映这一点(即您有@ 987654324@ 两次,"f ooba r"
丢失等)
在这个答案中,我假设你真的想要“字符串之间的所有可能组合,字符之间有空格”
【讨论】:
【参考方案6】:递归解决方案。 (对于更长的字符串可能需要使用sys.setrecursionlimit()
):
def gen_perm(my_str):
if len(my_str) <= 1 :
return [my_str]
rest_perms = gen_perm(my_str[1:])
all_perms = [my_str[0] + perm for perm in rest_perms ] + [my_str[0] + ' ' + perm for perm in rest_perms]
return all_perms
print(gen_perm("foobar"))
【讨论】:
【参考方案7】:使用 itertools 库(但它与 Titandrake 几乎相同):
import itertools
foobar = "foobar"
foobar_r = range(len(foobar))
for integer in range(2**5):
binary_mask = [ bit for bit in itertools.ifilter(lambda x: ( integer >>x)&0x01, foobar_r ) ]
spaces_mask = [ " " if i in binary_mask else "" for i in foobar_r ]
# Zip-it Crash-it Melt-it Upgrade-it
print integer, "".join([ "".join([str(char) for char in zip_char ]) for zip_char in itertools.izip(foobar,spaces_mask)])
【讨论】:
以上是关于如何生成字符之间带有空格的字符串的所有可能组合? Python的主要内容,如果未能解决你的问题,请参考以下文章