Python 如何避免冗余并在字符串组合中应用筛选器

Python 如何避免冗余并在字符串组合中应用筛选器,python,algorithm,itertools,Python,Algorithm,Itertools,我希望避免字符串列表中所有可能组合的冗余(例如,在我的上下文中,1122与2211是相同的,因此结果列表中只能有一个或另一个) 我还想在组合过程中应用过滤器。例如,我不希望结果中有任何包含3的字符串 我应该如何处理这个逻辑 此代码正在进行组合 >>> keywords = [''.join(i) for i in itertools.product(['11', '22', '33'], repeat = 2)] >>> keywords ['1111', '

我希望避免字符串列表中所有可能组合的冗余(例如,在我的上下文中,
1122
2211
是相同的,因此结果列表中只能有一个或另一个)

我还想在组合过程中应用过滤器。例如,我不希望结果中有任何包含
3
的字符串

我应该如何处理这个逻辑

此代码正在进行组合

>>> keywords = [''.join(i) for i in itertools.product(['11', '22', '33'], repeat = 2)]
>>> keywords
['1111', '1122', '1133', '2211', '2222', '2233', '3311', '3322', '3333']

这应该满足您的要求:

import itertools

def main():

    newkeywords = []
    keywords = ["".join(i) for i in itertools.product(["11", "22", "33"], repeat = 2)]
    for item in keywords:
        newitem = "".join(sorted(item))
        if "3" not in newitem and newitem not in newkeywords:
            newkeywords.append(newitem)
    print(newkeywords)

main()
结果:

['1111', '1122', '2222']

它会生成一个新列表,如果已排序项(使1122与2211相同)存在或数字“3”存在,则不要将其添加到新列表中。

根据您的实际数据,可能有更有效的方法来执行此操作,但下面的算法将起作用。我们通过简单的比较消除了重复项。我已将'3'的支票放入函数中。这比直接在列表理解中执行要慢一些,但它使代码更通用

import itertools

bases = ['11', '22', '33', '44']

def is_ok(u, v):
    ''' Test if a u,v pair is permitted '''
    return not ('3' in u or '3' in v)

keywords = [u+v for u, v in itertools.product(bases, repeat = 2) if u <= v and is_ok(u, v)]

通过过滤
itertools也可以实现这一点。使用替换的组合\u

代码

import itertools as it


bases = ["11", "22", "33", "44"]

[x+y for x,y in it.combinations_with_replacement(bases, 2) if "3" not in x+y]
# ['1111', '1122', '1144', '2222', '2244', '4444']
此版本更通用,不依赖于比较数字字符串


详细信息

从中我们可以理解为什么这样做有效:

在过滤元素未按排序顺序排列的条目(根据其在输入池中的位置)后,带有替换()的组合的代码也可以表示为
product()
的子序列

通过这种方式,每个项目都与一个唯一的索引相关联。比较两个项目的索引时,仅使用排序的组合生成一个项目。如前所述,其余索引将被丢弃

(0, 0)
(0, 1)
(0, 2)
(0, 3)
(1, 0)                                         # discarded
(1, 1)
...

有关此工具与
itertools.product

之间相似性的更多详细信息,请参阅。是否应跳过
2222
3333
?可能会循环并排序每个字符串,如果排序后的字符串在新列表中不存在,则添加原始字符串:如果这看起来是您想要的正确方向,我可以写出一个更好的答案。任何包含3的字符串都应该删除。如果您不想在输出中包含3,则应将这些字符串从输入中过滤到
product
。是否
repeat
始终为2?
def combinations_with_replacement(iterable, r):
    pool = tuple(iterable)
    n = len(pool)
    for indices in product(range(n), repeat=r):
        if sorted(indices) == list(indices):
            yield tuple(pool[i] for i in indices)
(0, 0)
(0, 1)
(0, 2)
(0, 3)
(1, 0)                                         # discarded
(1, 1)
...