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

fue*_*zig 81 python list

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

property_a = [545., 656., 5.4, 33.]
property_b = [ 1.2,  1.3, 2.3, 0.3]
...
Run Code Online (Sandbox Code Playgroud)

并列出具有相同长度的标志

good_objects = [True, False, False, True]
Run Code Online (Sandbox Code Playgroud)

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

good_indices = [0, 3]
Run Code Online (Sandbox Code Playgroud)

什么是产生新的列表的最简单的方法property_asel,property_bsel...只包含或者由指定的值True项或索引?

property_asel = [545., 33.]
property_bsel = [ 1.2, 0.3]
Run Code Online (Sandbox Code Playgroud)

ken*_*ytm 103

你可以使用列表理解:

property_asel = [val for is_good, val in zip(good_objects, property_a) if is_good]
Run Code Online (Sandbox Code Playgroud)

要么

property_asel = [property_a[i] for i in good_indices]
Run Code Online (Sandbox Code Playgroud)

后者更快,因为它good_indices的长度少于property_a,假设good_indices是预先计算而不是在运行中生成.


编辑:第一个选项相当于itertools.compress自Python 2.7/3.1以来可用.见@Gary Kerr的回答.

property_asel = list(itertools.compress(good_objects, property_a))
Run Code Online (Sandbox Code Playgroud)

  • @ 85:你为什么担心表现?写下你必须做的事情,如果它很慢,那么测试找出瓶颈. (4认同)

Wol*_*lph 22

我看到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]
    
    Run Code Online (Sandbox Code Playgroud)
  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]
    
    Run Code Online (Sandbox Code Playgroud)

  • 使用 Numpy 是一个很好的建议,因为 OP 似乎想将数字存储在列表中。二维数组会更好。 (2认同)

Gar*_*err 15

使用内置功能zip

property_asel = [a for (a, truth) in zip(property_a, good_objects) if truth]
Run Code Online (Sandbox Code Playgroud)

编辑

只看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
Run Code Online (Sandbox Code Playgroud)

  • 嗯,我发现使用压缩的代码更具可读性:)也许我有偏见,因为它完全符合我的要求. (5认同)
  • 我对这里使用“itertools.compress”感到不知所措。列表理解的可读性*远*高,而不必挖掘到底压缩在做什么。 (2认同)

Eyr*_*ire 8

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

property_asel = [ property_a[index] for index in good_indices ]
Run Code Online (Sandbox Code Playgroud)

这意味着属性选择将只执行与真实/必需索引一样多的轮次.如果您有许多属性列表遵循单个标记(true/false)列表的规则,则可以使用相同的列表推导原则创建索引列表:

good_indices = [ index for index, item in enumerate(good_objects) if item ]
Run Code Online (Sandbox Code Playgroud)

这将遍历good_objects中的每个项目(同时使用枚举记住其索引)并仅返回item为true的索引.


对于没有获得列表理解的任何人,这里是一个英文散文版本,代码以粗体突出显示:

列出每个索引组的索引,该项目存在良好对象枚举中,if(where)该项为True