当前位置: 首页 > 面试题库 >

列表理解过滤-“ set()陷阱”

逄学潞
2023-03-14
问题内容

一个合理的常见操作是list基于另一个过滤list。人们很快发现:

[x for x in list_1 if x in list_2]

对于大输入而言,速度很慢-为O(n * m)。uck 我们如何加快速度?使用aset进行过滤查找O(1):

s = set(list_2)
[x for x in list_1 if x in s]

这给出了很好的整体O(n)行为。但是,我经常看到甚至资深的编码人员也落入 The Trap ™:

[x for x in list_1 if x in set(list_2)]

阿克!这也是O(n * m),因为pythonset(list_2) 每次都 构建,而不仅仅是一次构建。

我以为故事就此结束了-python无法优化它,只能构建set一次。只是要注意陷阱。要忍受它。嗯

#python 3.3.2+
list_2 = list(range(20)) #small for demonstration purposes
s = set(list_2)
list_1 = list(range(100000))
def f():
    return [x for x in list_1 if x in s]
def g():
    return [x for x in list_1 if x in set(list_2)]
def h():
    return [x for x in list_1 if x in {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}]

%timeit f()
100 loops, best of 3: 7.31 ms per loop

%timeit g()
10 loops, best of 3: 77.4 ms per loop

%timeit h()
100 loops, best of 3: 6.66 ms per loop

呵呵,python(3.3) 可以 优化掉设置的文字。它比f()这种情况下甚至更快,大概是因为它可以用代替LOAD_GLOBALa
LOAD_FAST

#python 2.7.5+
%timeit h()
10 loops, best of 3: 72.5 ms per loop

Python
2显然没有进行此优化。我曾尝试进一步研究python3的功能,但不幸的是,dis.dis它无法探究理解表达式的内在性。基本上,所有有趣的东西都会变成MAKE_FUNCTION

所以现在我想知道-为什么python 3.x可以优化掉设置文字以仅构建一次,但不能构建一次set(list_2)


问题答案:

为了进行优化set(list_2),解释器需要证明list_2(及其所有元素)在迭代之间没有变化。在一般情况下,这是一个难题,如果口译员甚至不尝试解决它,也不会令我感到惊讶。

另一方面,html" target="_blank">集合文字不能在迭代之间更改其值,因此已知优化是安全的。



 类似资料:
  • 问题内容: 我碰巧发现自己有一个基本的过滤需求:我有一个列表,并且必须按项目的属性对其进行过滤。 我的代码如下所示: 但是后来我想,这样写会更好吗? 它更具可读性,并且如果需要性能,则可以取出以获得某些东西。 问题是:使用第二种方法是否有任何警告?有任何性能差异吗?我是否完全想念,应该以另一种方式来做到这一点(例如,使用而不是)吗? 问题答案: 我发现列表理解比 清晰得多,但请使用任何你更容易理解

  • 问题内容: 我开始使用django-tables2(从第一印象中就可以强烈推荐),我问自己如何实现列过滤。我找不到合适的文档,但是我确定它在那里。 问题答案: 答案有点晚了,但是无论如何…我也找不到任何合适的文档来进行列过滤。有很多方法可以做到这一点: 答:手动:我添加了一个包含要过滤的字段的表单,然后在我的视图中执行以下操作: 这很好用,但是不是那么干,因为它在视图中是硬编码的。 B.使用Sin

  • 4.5. 过滤列表 如你所知,Python 具有通过列表解析(第 3.6 节 “映射 list”)将列表映射到其它列表的强大能力。这种能力同过滤机制结合使用,使列表中的有些元素被映射的同时跳过另外一些元素。 过滤列表语法: [mapping-expression for element in source-list if filter-expression] 这是你所知所爱的 列表解析 的扩展。

  • 本文向大家介绍Python重构过滤器并映射到列表理解,包括了Python重构过滤器并映射到列表理解的使用技巧和注意事项,需要的朋友参考一下 示例 的filter或map功能应经常列表理解来代替。Guido Van Rossum在2005年的一封公开信中很好地描述了这一点: filter(P, S)几乎总是用来更清晰地写成,这具有巨大的优势,即最常见的用法是作为比较的谓词,例如,并且定义一个lamb

  • 问题内容: 我正在尝试使用python中的列表理解来扁平化列表。我的清单有点像 只是为了打印,然后在此列表中的单个项目我写了这段代码 然后我使用相同的逻辑通过列表理解来整理列表,但出现以下错误 如何使用列表理解来展平这种类型的列表? 问题答案: 单线: 可读版本: 使用嵌套列表理解:(与相比要慢一些):

  • 过滤字段的列表,每一个成员应该是数组或对象 $data = [ ['id'=>1, 'name'=>'a'], ['id'=>2, 'name'=>'b'], ]; // 两个毫无意义的实例化写法 $list = new FilterableList; $list = new FilterableList($data); // 只保留 name 字段 $list = new Fi