【问题标题】:Fastest way to extract elements from a list that not matched condition in python从python中不匹配条件的列表中提取元素的最快方法
【发布时间】:2011-10-17 13:21:12
【问题描述】:

我正在寻找最快的方式,以便在条件下从列表中提取所有元组成员。

示例: 从元组列表中(例如 [(0,0,4),(1,0,3),(1,2,1),(4,0,0)])我需要提取所有具有更多在第一个元组位置超过 3,然后在第二个元组位置超过 2,然后在最后一个元组位置超过 1。 在这个例子中应该提取(4,0,0)(->第一个条件),什么都没有(->第二个条件)和(0,0,4),(1,0,3)(->最后一个条件)。这个例子很小,我需要在数千个元组的列表上执行。

根据我从您的答案中生成的代码,以下是 sec 中的结果:

my_naive1,就像 Emil Vikström 提议的那样? 13.0360000134

my_naive2 110.727999926

蒂姆·皮茨克 9.8329999446

唐 12.5640001297

import itertools, operator, time, copy
from operator import itemgetter


def combinations_with_replacement_counts(n, r):  #(A, N) in our example.N individuals/balls in A genotypes/boxes
   size = n + r - 1
   for indices in itertools.combinations(range(size), n-1):
       #print indices
       starts = [0] + [index+1 for index in indices]
       stops = indices + (size,)
       yield tuple(map(operator.sub, stops, starts))


xp = list(combinations_with_replacement_counts(3,20))  # a very small case

a1=time.time()
temp=[]
for n in xp:
    for n1 in xp:

        for i in xp:
            if i[0] <= min(n1[0],n[0]) or i[1] <= min(n1[1],n[1]) or i[2] <= min(n1[2],n[2]):
                temp.append(i)


a2=time.time()
for n in xp:
    for n1 in xp:
        xp_copy = copy.deepcopy(xp)
        for i in xp:
            if i[0] > min(n[0],n[0]) or i[1] > min(n[1],n[1]) or i[2] > min(n[2],n[2]):
                xp_copy.remove(i)

a3=time.time()
for n in xp:
    for n1 in xp:
        output = [t for t in xp if t[0]<=min(n[0],n[0]) or t[1]<=min(n[1],n[1]) or t[2]<=min(n[2],n[2])]
a4=time.time()

for n in xp:
    for n1 in xp:
        l1 = sorted(xp, key=itemgetter(0), reverse=True)
        l1_fitered = []
        for item in l1:
            if item[0] <= min(n[0],n[0]):
                break
            l1_fitered.append(item)

        l2 = sorted(l1_fitered, key=itemgetter(1), reverse=True)
        l2_fitered = []
        for item in l2:
            if item[1] <= min(n[1],n[1]):
                break
            l2_fitered.append(item)

        l3 = sorted(l2_fitered, key=itemgetter(2), reverse=True)
        l3_fitered = []
        for item in l3:
            if item[2] <= min(n[2],n[2]):
                break
            l3_fitered.append(item)
a5=time.time()            



print "soluce my_naive1, like proposed by Emil Vikström?",a2-a1
print "soluce my_naive2",a3-a2
print "soluce Tim Pietzcker",a4-a3
print "soluce Don",a5-a4

【问题讨论】:

  • 我的例子很合适,这不是“我需要索引,但数据库太容易”的情况之一,而是“我需要一种快速的方法来实现巨大的马尔科夫超几何概率计算锁链”,所以重新收拾你傲慢的语气,试着向周围的世界敞开心扉,如果你不想帮忙,就走你的路。谢谢
  • 好吧,我不知道什么是超几何概率,甚至是马尔可夫链(听起来像是一条狗,还是巴甫洛夫?),但@eumiro 提出了一个重要问题:做你想要一个列表作为输出,还是三个列表(每个条件一个)?
  • soluce my_naive1,就像 Emil Vikström 提议的那样? 13.0360000134 soluce my_naive2 110.727999926 soluce Tim Pietzcker 9.83299994469 soluce Don 12.5640001297
  • 感谢分享性能结果!
  • 谢谢,但是那些min(n[1],n[1]) 电话是什么?你为什么要以嵌套的方式迭代xp,有时是三遍?现在,我认为这些比较毫无意义。

标签: python list extract


【解决方案1】:
>>> l = [(0,0,4), (1,0,3), (1,2,1), (4,0,0)]
>>> output = [t for t in l if t[0]>3 or t[1]>2 or t[2]>1]
>>> output
[(0, 0, 4), (1, 0, 3), (4, 0, 0)]

这很快,因为仅当 t[0]&gt;3False 时才评估 t[1]&gt;2(第三个条件相同)。因此,在您的示例列表中,只需要进行 8 次比较。

如果您改用生成器表达式,则可能会节省时间和内存(取决于您对过滤数据所做的操作):

>>> l = [(0,0,4), (1,0,3), (1,2,1), (4,0,0)]
>>> for item in (t for t in l if t[0]>3 or t[1]>2 or t[2]>1):
>>>     # do something with that item

【讨论】:

  • 我相信 OP 想要输出三个不同的列表。
  • 不,我需要一个符合条件的元组列表,并且不需要像假定 DON 那样订购(我将从它们包含的 3 个数字中为每个保留的元组计算一个概率)跨度>
【解决方案2】:

有三个列表,每个条件一个,然后使用 for 循环遍历输入集,将每个元组排序到正确的目标列表中。这将在 O(n)(线性)时间内执行,这是此问题可能最快的渐近运行时间。它也只会在列表中循环一次。

【讨论】:

    【解决方案3】:

    如果您不关心结果项目的顺序,我建议在排序列表中查找,并在第一个不匹配的项目上使用中断条件: 这将跳过列表尾部。

    from operator import itemgetter
    l = [(..., ..., ...), (...)]
    l1_source = sorted(l, key=itemgetter(0), reverse=True)
    l1_fitered = []
    for item in l1:
        if item[0] <= 3:
            break
        l1_fitered .append(item)
    
    l2 = sorted(l, key=itemgetter(1), reverse=True)
    ...
    

    【讨论】:

    • 我会尝试这种方式(我也在考虑排序方法是否可以变得更快)但是排序需要至少一个循环遍历列表?不?如果是这样,Tim Pietzcker 和 Emil Vikström 方法在大多数情况下应该做得更快,但如果我的条件与很多元组不匹配?
    • 这取决于列表的预排序方式。如果它是完全随机的,它可能会从这种有趣的方法中消耗掉性能优势。最后,如果它真的对性能至关重要,你将不得不计时。幸运的是,有一个 timeit 模块。
    • 这也取决于过滤条件的重度。看看docs.python.org/library/itertools.html:也许你能找到有用的东西
    猜你喜欢
    • 2018-12-05
    • 1970-01-01
    • 2011-06-01
    • 2017-07-07
    • 1970-01-01
    • 2019-09-06
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多