【问题标题】:Speeding up a function that outputs products with repeats in Python加速在 Python 中输出重复产品的函数
【发布时间】:2018-06-23 14:58:02
【问题描述】:

我编写了一个函数,它返回一个包含重复字符串的所有可能“产品”的列表(用于拼写检查程序):

def productRepeats(string):
    comboList = []

    for item in [p for p in product(string, repeat = len(list(string)))]:
        if item not in comboList:
            comboList.append("".join(item))

    return list(set(comboList))

因此,当print(productRepeats("PIP"))被输入时,他的输出是(我不管顺序是什么):

['PII', 'IIP', 'PPI', 'IPI', 'IPP', 'PPP', 'PIP', 'III']

但是,如果我尝试任何大于 5 位 (PIIIIP) 的内容,则输出大约需要 30 秒,即使只有 64 种方式

有什么方法可以加快速度,例如,获取字符串“GERAWUHGP”的列表需要半个多小时?

【问题讨论】:

  • 使comboList 成为set,所以查找是O(1),而不是O(n)。
  • @user3483203:实际上,按照编写的代码,OP确实需要转换为set,因为他们正在测试item in comboList,但添加了@ 987654328@ 到 comboList,因此他们的检查实际上并没有过滤掉任何重复项。
  • 请注意,您的产品规模增长得如此之快,以至于您的方法对于现实世界中的非平凡字符串来说不是很实用。我的意思是,“实用”这个词不是一个而是两个重复的字母,它会仍然生成一个 40M 长的列表。像“重复”这样的词将有一个超过 3.87 亿长的列表,如果你将它们全部实现,这将需要几分钟来生成和 20G 的内存。

标签: python string itertools


【解决方案1】:

在调用product() 之前 消除重复项

product(seq, repeat=len(seq)) 将产生重复的结果,如果 & 仅当 seq 包含任何重复的元素;例如,product('ABC', repeat=3) 将没有重复项,但 product('ABA', repeat=3) 将有一些重复项,因为 A 将被多次选择(并且由于 'ABA' 被用作参数三次) .先过滤掉string中的所有重复项,然后将结果传递给product,您就可以完全放弃product后的重复检查,因此您可以直接返回product的结果:

def productRepeats(string):
    return product(set(string), repeat=len(string))

【讨论】:

  • 有用,但我需要将输出作为字符串列表,而不是对象。此外,当我将 list() 添加到返回时,输出是元组列表
【解决方案2】:

您可以使用几个技巧:

  1. 使用列表推导式或map 执行迭代。
  2. 作为@jwodder explains,使用set(string) 以避免在以后检查重复项。

这是一个演示。我看到“你好”的改进约为 900 倍:

from itertools import product

def productRepeats(string):
    comboList = []

    for item in [p for p in product(string, repeat = len(list(string)))]:
        if item not in comboList:
            comboList.append("".join(item))

    return list(set(comboList))

def productRepeats2(string):
    return list(map(''.join, product(set(string), repeat=len(string))))

assert set(productRepeats2('hello')) == set(productRepeats('hello'))

%timeit productRepeats('hello')   # 127 ms
%timeit productRepeats2('hello')  # 143 µs

【讨论】:

    猜你喜欢
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-15
    相关资源
    最近更新 更多