我对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
的组合,但无法让它产生所需的结果。
答案 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']