【问题标题】:Fast multiset containment of lists in pythonpython中列表的快速多集包含
【发布时间】:2014-09-04 07:14:16
【问题描述】:

我有一个来自表查找的 int 迭代器,需要检查它们的多重集是否包含在给定的固定“多重集”ms 中。目前,我在开始时对ms 进行排序,然后在我的迭代器中对 int 进行排序并检查(排序列表的)多重集包含,如下所示:

vals = sorted(my_vals)
for it in ... :
    test_vals = sorted( i for i in it )
    if is_sublist(test_vals,vals):
        # do stuff

在哪里

def is_sublist(L1,L2):
    m = len(L1)
    n = len(L2)
    i = j = 0
    while j <= n:
        if i == m:
            return True
        elif j == n:
            return False
        a,b = L1[i], L2[j]
        if a == b:
            i += 1
            j+= 1
        elif a > b:
            j += 1
        else:
            return False
  • 通常,我的列表很短(1--20 个元素)
  • 我尝试使用Counter,但其初始化的时间劣势比遏制测试的时间优势更糟糕。
  • 我这样做了~10^6 次,所以我应该在cython 中这样做

任何想法或指针都会很好——谢谢! (抱歉,太早点击发帖按钮了……)

【问题讨论】:

  • is_sublist 是做什么的?您正在检查L1“支配”L2 的前缀,其中“支配”是指L1[i] &gt;= L2[i]。这是你想要的吗?
  • 顺便说一句:sorted(i for i in it) 可以写成sorted(it)
  • is_sublist(L1,L2) 返回 True 如果它 L2 包含等于 L1 的有序子列表。

标签: python multiset containment


【解决方案1】:
# edit: second attempt in response to Bakuriu's comment
#
from collections import Counter
from itertools import groupby
multiset = Counter(sorted(vals)) # only create one Counter object
for it in ...:
    grouped = groupby(sorted(it))
    if all(len(list(g)) <= multiset[k] for k, g in grouped):
        # do stuff



from operator import eq
# if you are using Python 2
from itertools import izip as zip
from itertools import starmap

vals = sorted(my_vals)
for it in ...:
    test_vals = sorted(it)
    zipped = zip(test_vals, vals)
    # check if test_vals' multiset is contained 
    # in vals' multiset but bale out as soon as
    # non-matching values are found.
    if all(starmap(eq, zipped)):
        # do stuff

【讨论】:

  • 等同于 OP 代码。在is_sublist 中,代码可能会将第一个参数中的相同元素与第二个参数中的多个元素进行比较,这是您无法用简单的map 模拟而无需使用迭代器的。
  • 一旦你这样做了sorted(it),我怀疑有什么比我的is_sublist 更快。此外,您的zip 忘记了来自vals 的必要信息,例如,如果test_vals[2,2] 并且vals[1,2,2],我有一个多集收容,但zip([2,2],[1,2,2]) 无法确定。
  • @ChristianStump 我能够使用 numba 的 @autojit 装饰器编译 is_sublist 函数,这样可以省去与 Cython 联系的麻烦。如果您可以访问该软件包,可能值得一试。我还打算将 vals 设为函数的局部变量而不是参数,因为这也会提高速度。
  • @superjump,我无法让 numba 运行,但稍后会再试一次,感谢您的想法!
猜你喜欢
  • 2011-12-27
  • 2012-05-24
  • 1970-01-01
  • 2013-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-05
  • 2012-06-16
相关资源
最近更新 更多