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_asel
, property_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个选项。
-
使用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]
-
使用列表理解和压缩它:
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仅限于数组的数组,这是你的例子。