特定情况下Python中的列表推导

问题描述

lst_a = [[1,2,3],[4,5,6],[7,8,9]]
lst_b = [[1,4,7],[6,4],[9,7]]

我的目标是检查 lst_a 中的所有嵌套列表,如果第一个条目 == lst_b 中任何元素的第一个条目。如果不是只复制那个子列表。在本例中,他不会复制 lst_a[0],而是复制 1 和 2。

我试图通过列表理解来实现我的目标,但它不起作用。

zero = [x[0] for x in lst_a]
if zero not in lst_b:
    # I don't kNow what to do here.

创建元组或字典是不可能的,因为整个过程处于循环中,每秒钟都有新数据进来,我尽量避免将重复项复制到列表中。

编辑:lst_b 应该在整个过程之后看起来像这样:

lst_b = [[1,9]]

解决方法

lst_b 中的所有第一个元素提取到一个集合中,以便您可以有效地检查成员资格。然后使用列表推导复制 lst_a 中符合您条件的所有子列表。

first_elements = {x[0] for x in lst_b}
result = [x for x in lst_a if x[0] not in first_elements]
,

有点难吃,但还不错:

lst_b.extend(x for x in lst_a if not any(x[0] == y[0] for y in lst_b)

如果您想要一个列表而不是修改lst_b,那么

lst_c = lst_b + [x for x in lst_a if not any(x[0] == y[0] for y in lst_b)]

无论哪种情况,我们都会检查 x 中的每个子列表 lst_a。如果子列表的第一个元素等于 any(x[0] == y[0] for y in lst_b) 中任何子列表的第一个元素,则 Truelst_b。如果不是,那么我们将在最终结果中包含 x

使用 any 允许我们在找到单个匹配项就足够时避免检查 lst_b 中的每个子列表。 (在某些情况下,这可能比首先创建一整套第一个元素更有效,如@barmar 的回答所示,但平均而言,这种方法可能更有效。)

,

可能有更有效的方法来做到这一点,但这达到了目标。

>>> [a for a in lst_a if a[0] not in [b[0] for b in lst_b]]
[[4,5,6],[7,8,9]]
,

另一种方式:

exclude=set(next(zip(*lst_b))) 
lst_b+=[sl for sl in lst_a if sl[0] not in exclude]
>>> lst_b
[[1,4,7],[6,4],[9,[4,9]]

说明:

  1. zip(*lst_b) 是矩阵 lst_b 的逆生成器,* 扩展子列表,这会创建一个生成器,依次产生 [(1,6,9),(4,8),(7,7)]。立>
  2. next(zip(*lst_b) 我们只需要逆的第一个元素:(1,9)
  3. set(next(zip(*lst_b))) 只需要它的 uniq 元素,所以变成了一个集合。你得到 {1,9}(顺序无关紧要)
  4. [sl for sl in lst_a if sl[0] not in exclude] 根据该条件过滤。
  5. lst_b+= 使用过滤后的元素扩展 lst_b

利润!

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...