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]