【问题标题】:How do I generate all possible combinations of a string with spaces between the characters? Python如何生成字符之间带有空格的字符串的所有可能组合? 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']

【问题讨论】:

  • 提示:你可以考虑在每个位置拆分一个字符串,然后递归地对每个子字符串做同样的事情
  • 你的输出怎么变化这么大?

标签: python string whitespace combinations


【解决方案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']

【讨论】:

【解决方案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)])
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-06
          • 1970-01-01
          • 2012-08-23
          相关资源
          最近更新 更多