请考虑以下问题:我想保留属于list2的list1的元素。所以我可以做这样的事情:
name.
zip(price, weight).
map(&%i[name price weight].method(:zip)).
map(&:to_h).
map(&Fruit.method(:create))
我需要对list1的不同示例(大约20000个不同的示例)和“常量”(冻结)list2重复相同的过程。
我如何加快这一过程?
我还知道以下属性:
1)list1具有重复的元素,并且没有排序,并且大约有10000(一万)个项目。
2)list2是一个巨大的排序列表(在Python中约为200000-20万个条目),每个元素都是唯一的。
首先想到的是,也许我可以使用一种二进制搜索。但是,有没有办法在Python中做到这一点?
此外,我不介意filtered_list是否具有与list1相同的项顺序。因此,也许我只能检查list1的未重复版本,并在删除list1中不属于列表2的元素之后,可以返回重复的项目。
在Python 3中有快速的方法吗?
答案 0 :(得分:2)
将list2
转换为set
:
# do once
set2 = set(list2)
# then every time
filtered_list = [w for w in list1 if w in set2]
x in list2
是顺序的; x in set2
使用与字典相同的机制,从而可以非常快速地进行查找。
如果list1
没有重复项,则将两者都转换为集合并采用集合交集是一种方法:
filtered_set = set1 & set2
但是如果有重复项,您就不得不像上面那样在list1
上进行迭代。
(如您所说,您甚至可以使用set1 - set2
看到要删除的元素,但是为了删除它们,您仍然会陷入循环中-性能不应有任何差异在过滤守护者与过滤垃圾之间,您仍然必须遍历list1
,因此无法克服以上方法。)
编辑以回应评论:如果可以,将list1
转换为Counter
可能会(编辑:否;需要测试!)加快处理速度。通常这样使用它(即,您永远没有列表,您总是只处理Counter
)。但是,如果每次执行上述操作时都必须将list1
预处理为counter1
,那再无济于事-创建Counter
将再次涉及到循环。