7

如何生成字符之间带有空格的字符串的所有可能组合?

[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']
4

7 回答 7

4
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']
于 2013-05-10T09:54:53.417 回答
2

这是我上面递归想法的实现:

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 个字符)会崩溃。

于 2013-05-10T09:51:48.457 回答
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']
于 2013-05-10T10:18:25.580 回答
1

这可能不是最有效的方法,但我会列出两个列表。一个有一个字母作为每个元素,另一个有每个字母后跟一个空格。(每次都跳过最后一个字母,因为它总是没有空格。)通过在每个字母的两个列表之间进行选择来生成可能的间距(可以建模为二进制数,其中 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]
于 2013-05-10T09:20:52.303 回答
1
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]并未反映这一点(即您有"f o o bar"两次,"f ooba r"丢失等)

在这个答案中,我假设你真的想要“字符串的所有可能组合,字符之间有空格”

于 2013-05-10T09:37:51.540 回答
1

递归解决方案。(可能需要使用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"))
于 2013-05-10T13:41:51.260 回答
0

使用 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)])
于 2013-05-10T09:47:44.943 回答