代码之家  ›  专栏  ›  技术社区  ›  fuenfundachtzig

Python:基于索引集从列表中选择子集

  •  68
  • fuenfundachtzig  · 技术社区  · 16 年前

    我有几个具有相同条目数的列表(每个都指定一个对象属性):

    property_a = [545., 656., 5.4, 33.]
    property_b = [ 1.2,  1.3, 2.3, 0.3]
    ...
    

    good_objects = [True, False, False, True]
    

    (可以很容易地用等效索引列表代替:

    good_indices = [0, 3]
    

    生成新列表的最简单方法是什么 property_asel , property_bsel , ... 只包含 True 条目还是索引?

    property_asel = [545., 33.]
    property_bsel = [ 1.2, 0.3]
    
    5 回复  |  直到 16 年前
        1
  •  146
  •   Devin kennytm    6 年前

    list comprehension :

    property_asel = [val for is_good, val in zip(good_objects, property_a) if is_good]
    

    property_asel = [property_a[i] for i in good_indices]
    

    后者更快,因为数量更少 good_indices 比…的长度 property_a 良好的指数 是预先计算的,而不是动态生成的。


    编辑 :第一个选项相当于 itertools.compress 从Python2.7/3.1开始提供。看到了吗 @Gary Kerr 的答案。

    property_asel = list(itertools.compress(property_a, good_objects))
    
        2
  •  31
  •   Wolph    16 年前

    我有两个选择。

    1. 使用numpy:

      property_a = numpy.array([545., 656., 5.4, 33.])
      property_b = numpy.array([ 1.2,  1.3, 2.3, 0.3])
      good_objects = [True, False, False, True]
      good_indices = [0, 3]
      property_asel = property_a[good_objects]
      property_bsel = property_b[good_indices]
      
    2. 使用列表并压缩:

      property_a = [545., 656., 5.4, 33.]
      property_b = [ 1.2,  1.3, 2.3, 0.3]
      good_objects = [True, False, False, True]
      good_indices = [0, 3]
      property_asel = [x for x, y in zip(property_a, good_objects) if y]
      property_bsel = [property_b[i] for i in good_indices]
      
        3
  •  17
  •   Gary Kerr    16 年前

    使用内置函数 zip

    property_asel = [a for (a, truth) in zip(property_a, good_objects) if truth]
    

    编辑

    看看2.7的新特性。现在,itertools模块中有一个函数与上面的代码类似。

    http://docs.python.org/library/itertools.html#itertools.compress

    itertools.compress('ABCDEF', [1,0,1,0,1,1]) =>
      A, C, E, F
    
        4
  •  9
  •   Eyrofire Dave Brunker    12 年前

    假设您只有项目列表和真实/必需索引列表,这应该是最快的:

    property_asel = [ property_a[index] for index in good_indices ]
    

    这意味着属性选择将只执行真实/所需索引的数量。如果有许多属性列表遵循单个标记(真/假)列表的规则,则可以使用相同的列表理解原则创建索引列表:

    good_indices = [ index for index, item in enumerate(good_objects) if item ]
    

    它遍历好对象中的每个项(同时使用enumerate记住其索引),并仅返回该项为真的索引。


    的索引 每一组 索引,项 枚举 好东西 , 如果 (其中)

        5
  •  -1
  •   FredAndre    12 年前

    from numpy import *
    property_a = array([545., 656., 5.4, 33.])
    property_b = array([ 1.2,  1.3, 2.3, 0.3])
    good_objects = [True, False, False, True]
    good_indices = [0, 3]
    property_asel = property_a[good_objects]
    property_bsel = property_b[good_indices]
    

    Numpy试图模仿Matlab/Scilab,但这是有代价的:您需要用关键字“array”声明每个列表,这会使脚本过载(Matlab/Scilab不存在这个问题)。请注意,此解决方案仅限于数字数组,在您的示例中就是这种情况。

    推荐文章