在python中生成一个字符串列表

时间:2014-01-04 02:22:56

标签: python combinations

我对python很新,所以我想我会试试这个快速的脚本......

给定一组输入词:即“dead”,“beef”,如何以编程方式生成给定长度和填充字符的所有可能字符串?

结果看起来像这样(使用0的填充,长度为12):

deadbeef0000
dead0beef000
dead00beef00
dead000beef0
dead0000beef
0deadbeef000
0dead0beef00
0dead00beef0
0dead000beef
00deadbeef00
00dead0beef0
00dead00beef
000deadbeef0
000dead0beef
0000deadbeef

生成此列表的天真方法可能是:

for x in range(0, 5):
  pre = '0' * x
  for y in range(0, 5):
    mid = '0' * y
    for z in range (0, 5):
      post = '0' * z
      val = pre + 'dead' + mid + 'beef' + post
      if len(val) == 12:
        print val

有更直接的方法吗?我已经查看了itertools的组合,但无法让它产生所需的结果。

5 个答案:

答案 0 :(得分:6)

可能是这样的:

>>> from itertools import permutations
>>> lst = ['dead', 'beef', '0', '0', '0', '0']
>>> for i in set(permutations(lst)):
...     ''.join(i)
... 
'beefdead0000'
'dead0beef000'
'dead000beef0'
'00dead0beef0'
'0beef000dead'
...

编辑:关注@TimPeters评论

>>> [''.join(i) for i in set(permutations(lst)) 
                                        if i.index('dead') < i.index('beef')]

或以更一般的方式:

>>> real_words = ['dead', 'beef']
>>> padding = 4
>>> [''.join(i) for i in set(permutations(real_words + ['0'] * padding)) 
                      if reduce(lambda x,y: i.index(x) < i.index(y), real_words)]

答案 1 :(得分:4)

假设,正如您的示例所示,您希望“真实单词”以原始顺序出现,这可以直接完成(每个所需的输出字符串只生成一次,没有重复,也不需要“清除”无关的字符串)。每个单词需要一个“插槽”,每个填充字符需要一个插槽,其中填充字符的总数是指定的最终长度减去单词长度的总和。在您的示例中,您有两个长度为4的单词,总单词长度为8,因此每个输出字符串中需要12-8 = 4个填充字符。这总共提供了6个插槽(2个用于单词,4个用于填充字符)。因此,输出字符串的总数为6-choose-2 = 6-choose-4 = 6 * 5/2 = 15.这也解释了如何使用itertools.combinations来获得结果:你选择了索引来自所有时隙索引的集合中的2个单词,或者 - 等效地 - 从所有时隙索引的集合中挑选4个填充字符的索引。这里的代码执行前者:

def get_strings(words, pad, length):
    from itertools import combinations
    nwords = len(words)
    npad = length - sum(len(word) for word in words)
    nslots = nwords + npad
    for ix in combinations(range(nslots), nwords):
        result = [pad] * nslots
        i = 0
        for j in ix:
            result[j] = words[i]
            i += 1
        yield "".join(result)

然后:

for s in get_strings(["dead", "beef"], "0", 12):
    print s

显示您想要的15个字符串。

答案 2 :(得分:1)

for x in range(0, 5):
    pre = '0' * x
    for y in range(0, 5-x):
        mid = '0' * y
        z = 5 - x - y
        post = '0' * z
        val = pre + 'dead' + mid + 'beef' + post
        print val

答案 3 :(得分:1)

我假设在您的示例中,您希望dead始终显示在beef之前。如果是这样,我相信下面的代码可以工作。

基本上,它所做的是它生成所需的填充字符数量的所有分区,这些分区的间隔数等于传入的字符串数量的一个以上。此解决方案使用生成器,以便生成字符串苍蝇(即懒惰)。请注意,除非len(padding_character) == 1

,否则无法正常使用
import itertools

def partitions(size, number):
    '''
Yields all partitions of `size` containing `number` compartments, where
a compartment may be 0, and where all permutations are returned
'''
    if number == 1:
        yield (size,)
    else:
        for i in range(0, size+1):
            for partition in partitions(size-i, number-1):
                yield (i,) + partition

def padding_generator(strings, padding_character, total_length):
    strings_length = sum(map(len, strings))
    padding_length = total_length - strings_length
    num_padding_locations = len(strings)+1
    for partition in partitions(padding_length, num_padding_locations):
        result = ''
        for padding_count, string in itertools.zip_longest(partition, strings, fillvalue=''):
            result += padding_character*padding_count
            result += string
        yield result

for string in padding_generator(['dead', 'beef'], '0', 12):
    print(string)

结果:

deadbeef0000
dead0beef000
dead00beef00
dead000beef0
dead0000beef
0deadbeef000
0dead0beef00
0dead00beef0
0dead000beef
00deadbeef00
00dead0beef0
00dead00beef
000deadbeef0
000dead0beef
0000deadbeef

答案 4 :(得分:1)

只是为了好玩,直接递归的方法:

def padded(to_pad, pad_with, pad_amount):
    if not to_pad:
        yield pad_with * pad_amount
        return
    for i in range(pad_amount + 1):
        for suffix in padded(to_pad[1:], pad_with, pad_amount - i):
            yield pad_with * i + to_pad[0] + suffix

测试:

>>> list(padded(['dead', 'beef'], '0', 4))
['deadbeef0000', 'dead0beef000', 'dead00beef00', 'dead000beef0', 'dead0000beef',
 '0deadbeef000', '0dead0beef00', '0dead00beef0', '0dead000beef', '00deadbeef00',
 '00dead0beef0', '00dead00beef', '000deadbeef0', '000dead0beef', '0000deadbeef']