我需要对所有字符进行一些限制。我想在 2 个地方最多有 7 个相同的字符。我能做到吗?
我得到了我想要的迭代工具combination_with_replacement
.但我需要为每个角色设定一个限制。
from itertools import combinations_with_replacement
def combine(arr, s):
return list(combinations_with_replacement(symbols, s))
symbols = "Ga1SRT2"
max_length = 7
set = 7
print(combine(symbols, set))
例。现在我得到'G'
、'G'
、'G'
、'a'
、'S'
、'S'
、'R'
中的一个,我想只得到 2G
,而不是 3。
可能不是最有效的,因为它计算然后丢弃大量数据,但后处理对元素进行计数并仅保留最多有 2 次重复的元素有效:
from itertools import combinations_with_replacement
import collections
def combine(arr, s):
return [x for x in combinations_with_replacement(symbols, s) if max(collections.Counter(x).values()) <= 2]
如果成员重复不超过两次,列表理解中的if max(collections.Counter(x).values()) <= 2
x
只会保持x
。
我们还可以重用文档中提供的相当于combinations_with_replacement
的python(可能在大多数平台上作为本机代码提供(,并执行小而便宜的算法优化(请注意,我们仍然需要用collections.Counter
过滤(
def combinations_with_replacement(iterable, r):
# combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC with tweak to avoid
# to issue obvious data that is going to be filtered out
pool = tuple(iterable)
n = len(pool)
if not n and r:
return
indices = [0] * r
yield tuple(pool[i] for i in indices)
while True:
for i in reversed(range(r)):
if indices[i] != n - 1:
break
else:
return
indices[i:] = [indices[i] + 1] * (r - i)
if r - i < 3:
yield tuple(pool[i] for i in indices)
最后yield
在原始源中无条件地完成。我的建议是检查r - i < 3
,好像它更大,indices
保证包含相同的索引两次以上。
使用您的输入,itertools
中的标准combinations_with_replacement
算法会生成 1716 个值,这些值需要使用元素计数进行过滤。
通过我的修改,它只产生 1255 个值,因此需要后处理的数据减少了 25%。替换算法是纯python而不是C,但是不确定它是否更快。