【问题标题】:Filtering two lists simultaneously同时过滤两个列表
【发布时间】:2013-08-02 10:47:28
【问题描述】:

我有三个列表:

del_ids = [2, 4]
ids = [3, 2, 4, 1]
other = ['a', 'b', 'c', 'd']

我的目标是删除del_ids,结果是

ids = [3, 1]
other = ['a', 'd']

我已经尝试为要保留的元素制作一个掩码 (mask = [id not in del_ids for id in ids]),我计划在两个列表上都应用这个掩码。

但我觉得这不是pythonic的解决方案。你能告诉我怎样才能做得更好吗?

【问题讨论】:

    标签: python filtering


    【解决方案1】:

    再次压缩、过滤和解压缩:

    ids, other = zip(*((id, other) for id, other in zip(ids, other) if id not in del_ids))
    

    zip() 调用将每个 id 与相应的 other 元素配对,生成器表达式过滤掉 iddel_ids 中列出的任何配对,然后 zip(*..) 梳理出剩余的再次配对到单独的列表中。

    演示:

    >>> del_ids = [2, 4]
    >>> ids = [3, 2, 4, 1]
    >>> other = ['a', 'b', 'c', 'd']
    >>> zip(*((id, other) for id, other in zip(ids, other) if id not in del_ids))
    [(3, 1), ('a', 'd')]
    

    【讨论】:

    • 感谢您的回答,在这种情况下,您能告诉我星星是干什么用的吗?这种形式的理解对我来说是新的。 :O
    • @BarnabasSzabolcs:它将序列(来自生成器表达式的所有对)作为单独的参数应用于zip() 函数。 zip() 看到 zip(pair1, pair2, pair3, etc.),然后将所有这些对压缩到两个列表中。
    • @BarnabasSzabolcs:(.. for .. in ..) 构造是一个生成器表达式。它很像列表推导 ([.. for .. in ..]),只是它不会先在内存中构建新列表。
    • 啊啊,我明白了,谢谢!获得许可后,我会接受答案。
    • 哇,真的吗?看起来我将能够在几年内记住并使用它......
    【解决方案2】:

    压缩、过滤、解压:

    ids, other = zip(*filter(lambda (id,_): not id in del_ids, zip(ids, other)))
    

    【讨论】:

    • @Martijn:过滤器返回恰好包含 2 个元组的过滤列表,因此我可以安全地解压它们。该死的你是对的,我做了更正。
    • 是的,直到您的过滤器返回多于或少于 2 个元组。在您了解它的作用之前,不要复制我的解决方案进行细微的更改。 :-P
    • @MartijnPieters:实际上,我在查看您的答案之前已经写好了答案。我想伟大的思想是一样的;-P
    【解决方案3】:

    转换为 pandas 数据框并应用掩码:

    del_ids = [2, 4]
    ids = [3, 2, 4, 1]
    other = ['a', 'b', 'c', 'd']
    df = pd.DataFrame({'ids':ids,'other':other})
    df = df[~df.ids.isin(del_ids)]
    ids = df['ids'].tolist()
    other = df['other'].tolist()
    

    【讨论】:

      【解决方案4】:

      为了避免学习棘手的语法,请分两步完成。

      other = [o for my_id, o in zip(ids, other) if my_id not in del_ids]
      ids = [my_id for my_id in ids if my_id not in del_ids]
      

      缺点
      您必须以正确的顺序执行语句,因此如果由于某种原因顺序更改,则存在错误的风险。

      优势
      这很简单,因此您下次想要这样做时不必搜索 Stackoverflow。

      【讨论】:

      • 我喜欢你的方法,因为它很干净。
      • 另外,我希望id 不是 python 中的保留字...因为 id 将是一个常见的变量名。拥有i 让我感到困惑,因为i 通常指的是整数循环索引,而不是id。如果无论如何它是python的实现细节,为什么他们没有__id__()而不是id()?那么,现在最糟糕的是,有一个错误命名的变量或有一个隐藏内置变量的变量? Martijn 似乎认为前者更糟。
      • 谢谢 Barney,我更改了变量名。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-07
      • 1970-01-01
      • 1970-01-01
      • 2020-10-23
      • 2014-06-03
      相关资源
      最近更新 更多