【问题标题】:Keeping track of processed lists跟踪处理的列表
【发布时间】:2021-12-04 03:28:19
【问题描述】:

我有一个工作流程来处理列表,并跟踪我在字典中看到的列表 - 因为当我找到已经看到的列表时,我可以传递它。需要注意的是,具有相同元素的两个列表以不同的方式排列被认为是重复的。所以举个简单的整数列表例子:[3, 1, 5, 6][5, 3, 6, 1] 是等价的。

我的做法是,将tuple(sorted(L)) 放入我的字典中。所以对于上面的例子seen 看起来像:

seen = {..., (1, 3, 5, 6): 1, ...}

这具有对我可能需要处理的每个列表进行恒定时间查找的好处。然而问题是,为了检查给定列表是否在seen 中,我必须对其执行tuple(sorted(L))。事实证明,对于大量数据,这变得令人望而却步,以至于占用了我整个过程总时间的 50% 以上。

我想以某种方式使用collections.Counter - 因为Counter[3, 1, 5, 6]Counter[5, 3, 6, 1] 将评估相等。但是 Counter 对象不能用作字典键。如何保持我的字典查找,但不执行上述排序操作?提前致谢。

编辑:在查看使用frozenset 的建议时,我意识到我遗漏了一件重要的事情,那就是元素可以重复。因此,虽然上面的两个列表比较相等,但 [3, 1, 5, 6][3, 3, 1, 5, 6, 6] 需要被视为不同的。由于frozenset 操作会删除重复项,因此这里不是一个选项。

【问题讨论】:

  • 对此完全不确定,但frozenset 会减少时间消耗吗?同样,我不知道实现细节。
  • @j1-lee 我怀疑最终会花费时间的排序、内存分配和过线性时间复杂度。
  • @Vatine 很高兴知道!谢谢:)
  • 您的列表和计数器有多大?
  • 我不认为将元组设置为 dict 键是一个好主意。也许将它们转换为字符串?这样,不同顺序的元组字符串将被视为不重复。

标签: python list algorithm


【解决方案1】:

正如其他人指出的那样,frozenset 是您的最佳选择:

seen = set()

list_1, list_2, list_3 = [3, 1, 5, 6], [5, 3, 6, 1], [1, 2, 3]

print(frozenset(list_1) in seen)
seen.add(frozenset(list_1))
print(frozenset(list_1) in seen)
print(frozenset(list_2) in seen)
print(frozenset(list_3) in seen)

frozenset 将一个可迭代对象作为参数,因此实例化该集合需要 O(n)。根据this previous response,查找的平均 O(1) 与标准 set 相同。无论哪种方式,您都可以节省非常昂贵的排序操作,即 O(n log n)。

【讨论】:

  • 感谢您的建议。这会很好用,但我忽略了一个重要的要求,我在我的帖子中进行了编辑。 frozenset 将删除我需要保留的重复项。
  • 这听起来不对,你不能真正考虑设置大小一次非恒定,然后另一次恒定。
【解决方案2】:

如果您确实有很多重复项,那么也许使用 frozenset of Counter 项目?

>>> from collections import Counter
>>> frozenset(Counter([3, 3, 1, 5, 6, 6]).items())
frozenset({(1, 1), (3, 2), (6, 2), (5, 1)})

Counter 项的排序元组:

>>> tuple(sorted(Counter([3, 3, 1, 5, 6, 6]).items()))
((1, 1), (3, 2), (5, 1), (6, 2)) 

【讨论】:

  • 这两个实际上都大大增加了我的执行时间。我对frozensetCounter 的了解还不够,不能说这是否令人惊讶。事实证明,我的大型流程效率低下需要解决,所以我在这里尝试做的事情可能没有实际意义,但无论如何仍然是一个有趣的问题。
猜你喜欢
  • 1970-01-01
  • 2020-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-12
相关资源
最近更新 更多