Python 删除元组的智能方法

Python 删除元组的智能方法,python,tuples,Python,Tuples,我有一个元组列表,如下所述(该元组按第二个值的降序排序): 给定一个阈值,丢弃第二个值小于该阈值的所有元组的最佳方法是什么 我有超过500万个元组,因此不想逐个元组进行比较,从而删除或添加到另一个元组列表中

我有一个元组列表,如下所述(该元组按第二个值的降序排序):

给定一个阈值,丢弃第二个值小于该阈值的所有元组的最佳方法是什么


我有超过500万个元组,因此不想逐个元组进行比较,从而删除或添加到另一个元组列表中 定义一个相似的

您可以使用
myarray['f1']
访问元组的第二个元素,它提供了一个浮点数组。你可以使用技术来过滤你想要的元素,比如

my_array[myarray['f1'] < threshold]
myu数组[myarray['f1']

仅保留
f1
小于
阈值的条目。

由于元组已排序,您只需搜索值低于阈值的第一个元组,然后使用切片表示法删除其余值:

index = next(i for i, (t1, t2) in enumerate(myTup) if t2 < threshold)
del myTup[index:]
这里的缺点是删除可能在线性时间内发生,因为Python必须将整个内存块移回。。。除非Python在删除从
0
开始的片段方面很聪明。(有人知道吗?)

最后,如果您真的愿意更改数据结构,您可以这样做:

[(-9, 'a'), (-8, 'b'), (-7, 'c'), (-6, 'd'), (-5, 'e'), (-4, 'f'), 
 (-3, 'g'), (-2, 'h'), (-1, 'i'), (0, 'j')]
>>> index = bisect.bisect(myTup, (-threshold, None))
>>> del myTup[index:]
>>> myTup
[(-9, 'a'), (-8, 'b'), (-7, 'c'), (-6, 'd')]
(请注意,Python3会抱怨
None
比较,因此可以使用类似
(-threshold,chr(0))
的内容。)


我的怀疑是,我在开始时建议的线性时间搜索在大多数情况下都是可以接受的。

可能比@好奇的代码快一点:

newTup=[]
for tup in myTup:
    if tup[1]>threshold:
        newTup.append(tup)
    else:
        break
因为元组是有序的,所以不必遍历所有元组

另一种可能性是,使用二分法,找到最后一个元素的索引
i
,它高于阈值。然后你会做:

newTup=myTup[:i]

我认为最后一种方法是最快的。

你也可以使用
itertools
例如

from itertools import ifilter
iterable_filtered = ifilter(lambda x : x[1] > threshold, myTup)
如果您想要一个iterable筛选列表,或者只需要:

filtered = filter(lambda x: x[1] > threshold, myTup)
直接进入列表


我对这些方法的相对性能不太熟悉,必须对它们进行测试(例如在中)。

这里有一种奇特的方法,在执行对分之前将列表包装在类似列表的对象中

import bisect

def revkey(items):
    class Items:
        def __getitem__(self, index):
            assert 0 <= index < _len
            return items[_max-index][1]
        def __len__(self):
            return _len
        def bisect(self, value):
            return _len - bisect.bisect_left(self, value)
    _len = len(items)
    _max = _len-1
    return Items()

tuples = [('a', 9), ('b', 8), ('c', 7), ('d', 6), ('e', 5), ('f', 4), ('g', 3), ('h', 2), ('i', 1), ('j', 0)]

for x in range(-2, 12):
    assert len(tuples) == 10
    t = tuples[:]
    stop = revkey(t).bisect(x)
    del t[stop:]
    assert t == [item for item in tuples if item[1] >= x]
导入对分 def revkey(项目): 类别项目: 定义uu获取项目uu(自身,索引): 断言0=x]
排序值的优点。用二进制搜索来加快速度怎么样?你不能像那样使用对分,因为你只需要比较阈值而不需要比较字母。
对分
参数将非常有用……而且,对分只按升序排序。根据,看起来他们建议创建一个列表(将您的键函数映射到原始列表上)并在该列表上进行对分。这是一个非常困难的正确操作(在我认为这很愚蠢之前,我正在制作一个反向视图包装器)。
对分
模块肯定不如它方便。是的,我也这么认为。我已经在comp.lang.python上写过了,只是想看看大家对这个事实有什么看法。实际上,我认为二进制搜索很容易实现,所以我不明白为什么它们不应该提供这样的基本功能。也没有缺点。。你只需要记住,每次都会重新计算“键”并决定要做什么。既然你的列表已经排序了:不如先做一次搜索,找出阈值以下的第一个元组的索引。+1:这就是我上面想的那种事情。经过深思熟虑,我确实有点惊讶,我以前从未需要过相反的观点。
from itertools import ifilter
iterable_filtered = ifilter(lambda x : x[1] > threshold, myTup)
filtered = filter(lambda x: x[1] > threshold, myTup)
import bisect

def revkey(items):
    class Items:
        def __getitem__(self, index):
            assert 0 <= index < _len
            return items[_max-index][1]
        def __len__(self):
            return _len
        def bisect(self, value):
            return _len - bisect.bisect_left(self, value)
    _len = len(items)
    _max = _len-1
    return Items()

tuples = [('a', 9), ('b', 8), ('c', 7), ('d', 6), ('e', 5), ('f', 4), ('g', 3), ('h', 2), ('i', 1), ('j', 0)]

for x in range(-2, 12):
    assert len(tuples) == 10
    t = tuples[:]
    stop = revkey(t).bisect(x)
    del t[stop:]
    assert t == [item for item in tuples if item[1] >= x]