Python:根据索引集从列表中select子集

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

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_aselproperty_bsel ,最简单的方法是什么?它只包含由True条目或索引指示的值。

 property_asel = [545., 33.] property_bsel = [ 1.2, 0.3] 

你可以使用列表理解 :

 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的数量less于good_indices的长度,假设good_indices是预先计算的而不是即时生成的。


编辑 :第一个选项等同于自Python 2.7 / 3.1以来可用的itertools.compress 。 见@加里·克尔的答案。

 property_asel = list(itertools.compress(good_objects, property_a)) 

我看到2个选项。

  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] 

使用内置的函数zip

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

编辑

只要看看2.7的新function。 现在在itertools模块中有一个类似于上面代码的函数。

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

 itertools.compress('ABCDEF', [1,0,1,0,1,1]) => A, C, E, F 

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

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

这意味着房地产select只会有真实/必需的指数。 如果您有很多属性列表遵循单个标签(true / false)列表的规则,则可以使用相同的列表理解原则创build索引列表:

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

这遍历了good_objects中的每个项目(同时用枚举记住它的索引),并只返回项目为真的索引。


对于没有得到清单理解的人来说,这里是一个英文散文版本,其代码以粗体突出显示:

列出每个索引的索引,这个索引是存在一个好的对象 枚举中的, 如果 (where)该项是真的

Matlab和Scilab语言提供了一个比Python更简单,更优雅的语法,因此我认为您可以做的最好的方法是使用Python中的Numpy包来模拟Matlab / Scilab。 通过这样做你的问题的解决scheme是非常简洁和优雅:

 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中不存在)。 请注意,这个解决scheme仅限于数组的数组,这是你的例子。