如何生成字符之间带有空格的字符串的所有可能组合? 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']

【讨论】:

非常优雅。我从没想过这样使用productreversed =)【参考方案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的主要内容,如果未能解决你的问题,请参考以下文章

使用多线程生成字符串的所有组合

如何在 vi 编辑器中搜索带有空格和特殊字符的字符串

使用一组字符串生成所有可能的组合

为字符串列表生成所有组合

生成所有可能的组合

如何从PHP和Javascript中的字符串中删除所有空格[重复]