获取布尔列表的truthy元素的索引作为列表/元组

时间:2012-10-25 20:16:21

标签: python json list

给定一个布尔列表,例如[True, False, False, True, False, True],什么是最快方式来获取包含Truthy元素的索引(从1开始,而不是零索引)的列表/元组在原始列表中?因此,对于上面的列表,它应该返回[1, 4, 6](1, 4, 6)

我正在使用这样的发电机:

def get_truthy_ones(self, bool_list):
    return (idx + 1 for idx, value in enumerate(bool_list) if value)

但是,当我想在JSON对象中对结果进行编码时,这会产生问题,因为JSON不会对生成器进行编码。

4 个答案:

答案 0 :(得分:12)

[i for i, elem in enumerate(bool_list, 1) if elem]

答案 1 :(得分:3)

将括号切换为方括号以返回列表而不是生成器:

def get_truthy_ones(self, bool_list):
    return [idx for idx, value in enumerate(bool_list, 1) if value]

或者使用您的原始功能,然后从生成器创建一个列表:

list(get_truthy_ones(self, bool_list))

答案 2 :(得分:2)

仅仅因为可以完成,itertools.compress()的替代版本。我认为这比其他例子的可读性差,所以我不推荐它。

>>> list(itertools.compress(*zip(*enumerate([True, False, False, True, False, True], 1))))
[1, 4, 6]

编辑:

python -m timeit -s "import itertools" -s "values = [True, False]*10000" "list(itertools.compress(*zip(*enumerate(values, 1))))"
100 loops, best of 3: 2.88 msec per loop

python -m timeit -s "import itertools" -s "values = [True, False]*10000" "[index for index, value in enumerate(values, 1) if value]"
1000 loops, best of 3: 1.11 msec per loop
事实上,速度明显慢,所以绝对不能使用。

答案 3 :(得分:1)

如果有办法将列表转换为numpy数组,使用numpy.where()应该更快:

> python -m timeit -s "import numpy" -s "values = numpy.array([True, False]*10000)" "numpy.where(values)"
1000 loops, best of 3: 392 usec per loop

> python -m timeit -s "import itertools" -s "values = [True, False]*10000" "[index for index, value in enumerate(values, 1) if value]"
100 loops, best of 3: 2.1 msec per loop

但我可能会在设置中进行转换而在这里作弊。