【问题标题】:Generating Unique Permutations in Python [duplicate]在 Python 中生成唯一排列
【发布时间】:2013-03-24 06:07:35
【问题描述】:

我正在寻找列表的唯一排列,x = ["$5", "$10", "$10", "TAX", "$5", "20%", "BOGO", "BOGO" , "TAX"] 9 个一组

我现在正在做的是

from itertools import permutations
x = ["$5", "$10", "$10", "TAX", "$5", "20%", "BOGO", "BOGO", "TAX"]
combos = []
for i in permutations(x, 9):
    if i not in combos:
        combos.append(i)
print combos

但是,这需要很长时间才能运行,我想知道是否有人可以给我更多 有效的解决方案。

【问题讨论】:

    标签: python


    【解决方案1】:

    if i not in combos: 需要很长时间,因为列表中的成员资格测试(最坏情况)是 O(N)——它必须扫描每个元素。您可以改用set

    >>> from itertools import permutations
    >>> x = ["$5", "$10", "$10", "TAX", "$5", "20%", "BOGO", "BOGO", "TAX", "BOGO"]
    >>> %time p = set(permutations(x, 9))
    CPU times: user 0.88 s, sys: 0.01 s, total: 0.90 s
    Wall time: 0.90 s
    >>> len(p)
    75600
    

    【讨论】:

    • 非常感谢您的帮助,这一切都很好!
    【解决方案2】:

    关于使用快速集合结构的建议很好,但如果您不首先生成不需要的项目,您将获得最佳结果。让我们对x做一个稍微不同的表示:

    from collections import OrderedDict
    x = OrderedDict([("$5", 2), ("$10", 2), ("TAX", 2), ("20%", 1), ("BOGO", 3)])
    

    那么,下面的函数应该让你得到非重复排列:

    from copy import copy
    def permutations_unique(x, curr_list=[]):
        if not x:
            yield curr_list
            return
        last_item = None
        if curr_list:
            last_item = curr_list[-1]
        for item in x:
            if item != last_item:
                for j in range(1, x[item] + 1):
                    xchild = copy(x)
                    xchild[item] -= j
                    if xchild[item] == 0:
                        del xchild[item]
                    for y in permutations_unique(xchild, curr_list + [item] * j):
                        yield y
    

    这是一个递归。在每个步骤中,我们选择项目重复次数。另外,我们避免在递归的下一级选择相同的项目。

    对于您的问题实例,此代码比使用 set 的方法慢。但是,请尝试使用 x = [1] * 30 作为反例。

    【讨论】:

      【解决方案3】:

      运行需要很长时间的原因是,当您将元素附加到列表时,每次查找需要更长的时间,因为它必须搜索(平均)列表的一半。更好的方法是使用字典:

      combos = {}
      

      还有:

      if i not in combos:
          combos[i] = None # Just to put something there unless you need to store a value
      

      这利用了hash maps 的查找性能。


      如果您只是进行成员资格测试,请按照 DSM 的建议使用集合。

      【讨论】:

      • 这比使用set() 更好吗?
      • 不,集合更好,因为它更具可读性。去找 DSM 的答案。
      猜你喜欢
      • 2018-11-08
      • 2019-11-27
      • 1970-01-01
      • 2012-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-26
      • 2015-09-25
      相关资源
      最近更新 更多