【问题标题】:Remove elements from python list based on filter基于过滤器从python列表中删除元素
【发布时间】:2017-01-02 09:16:01
【问题描述】:

我在 Python 中有 3 个列表。

list_a = [10., 20., 30., 12.]
list_b = [30., 20., 60., 12.]
list_c = [10., 80., 90., 12.]

我想将这些元素放在list_b 和list_c 中,其中list_a 中的值是<= 15。因此结果变为:

list_b = [20., 60.]
list_c = [80., 90.]

有没有办法在没有 for 循环的情况下做到这一点? (列表理解没问题)

【问题讨论】:

  • 没有循环?我不这么认为。 list_b 也不应该是 [30.,20.,60.,] 吗?
  • 你没有使用 Numpy,是吗?使用 Numpy 数组可以轻松做到这一点。
  • @DavidZ 我正在使用 numpy,有没有一种紧凑的方法可以做到这一点?
  • @snakecharmerb 返回新列表是可以的

标签: python list list-comprehension


【解决方案1】:

如果您按照您所说的那样使用 numpy,在 cmets 中,您可以简单地从 a 创建一个布尔索引,并在 b 和 c 中屏蔽元素:

import numpy as np

list_a = np.array([10., 20., 30., 12.])
list_b = np.array([30., 20., 60., 12.])
list_c = np.array([10., 80., 90., 12.])

list_b = list_b[list_a>15]
list_c = list_c[list_a>15]

print list_a
print list_b
print list_c

输出:

[ 10.  20.  30.  12.]
[ 20.  60.]
[ 80.  90.]

您可以通过.tolist() 方法将lists_b 和list_c 转换为Python list type。

【讨论】:

    【解决方案2】:

    您可以使用鲜为人知的itertools.compress 类来执行此操作。见Filter list using Boolean index arrays

    >>> import itertools
    >>> list_a = [10., 20., 30., 12.]
    >>> list_b = [30., 20., 60., 12.]
    >>> list_c = [10., 80., 90., 12.]
    >>> bool_list = [item > 15 for item in list_a]
    >>> bool_list
    [False, True, True, False]
    >>> list_b = list(itertools.compress(list_b, bool_list))
    >>> list_b
    [20.0, 60.0]
    >>> list_c = list(itertools.compress(list_c, bool_list))
    >>> list_c
    [80.0, 90.0]
    

    【讨论】:

      【解决方案3】:

      您可以使用zip() 编写一个单行来过滤列表:

      list_b, list_c = zip(*[(b, c) for a, b, c in zip(list_a, list_b, list_c) if a>15])
      

      list_b 和 list_c 持有的最终值将是:

      >>> list_b
      (20.0, 60.0)
      >>> list_c
      (80.0, 90.0)
      

      【讨论】:

        【解决方案4】:

        你可以使用列表推导吗?

        你可以这样做:

        list_a = [10., 20., 30., 12.]
        list_b = [30., 20., 60., 12.]
        list_c = [10., 80., 90., 12.]
        list_b = [ el for (i, el) in enumerate(list_b) if (list_a[i] > 15) ]
        list_c = [ el for (i, el) in enumerate(list_c) if (list_a[i] > 15) ]
        

        这里写了Snipper,我没有测试过,但你看到了大致的想法。

        我假设所有列表的长度相同。如果list_a 更短,并且您想删除丢失位置上的元素,您可以这样做:

        list_b = [ el for (i, el) in enumerate(list_b) if (i<len(list_a) and list_a[i] > 15) ]
        

        如果你想保留它们,只需反转符号和布尔运算符:

        list_b = [ el for (i, el) in enumerate(list_b) if (i>=len(list_a) or list_a[i] > 15) ]
        

        【讨论】:

          【解决方案5】:

          你可以zip()如下:

          >>> list_a = [10., 20., 30., 12.]
          >>> list_b = [30., 20., 60., 12.]
          >>> list_c = [10., 80., 90., 12.]
          >>>
          >>> [j for i,j in zip(list_a, list_b) if i >= 15]
          [20.0, 60.0]
          >>>
          >>> [j for i,j in zip(list_a, list_c) if i >= 15]
          [80.0, 90.0]
          

          【讨论】:

            【解决方案6】:
            list_a = [10., 20., 30., 12.]
            list_b = [30., 20., 60., 12.]
            list_c = [10., 80., 90., 12.]
            drop = [i for i,v in enumerate(list_a) if v <=15]
            b = [v for i,v in enumerate(list_b) if not i in drop]
            c = [v for i,v in enumerate(list_c) if not i in drop]
            

            【讨论】:

            • 这不是一个完整的答案。也请添加说明,以供日后参考
            猜你喜欢
            • 1970-01-01
            • 2011-02-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-22
            • 2010-09-20
            相关资源
            最近更新 更多