我有一个值列表:
a = [1,2,3,4]
相应的布尔人名单:
b = [True, True, False, True]
我想将b映射到一个这样的值,即我得到所有的值,使得它们在b中的对应值为“True”。所以这个例子的答案是[1,2,4]
我能想到的唯一方法是循环遍历b的元素,获取True的索引,然后在a中检索相应的索引。如下所示:
def maplist(l1, l2):
# list1 is a list of Booleans to map onto list2
l2_true = []
for el in range(len(l1)):
if l1[el] == True:
l2_true.append(l2[el])
return l2_true
有更好的方法吗?
答案 0 :(得分:3)
这是一个列表理解,应该做你想要的:
[v for i, v in enumerate(a) if b[i]]
另一种方法:
[x for x, y in zip(a, b) if y]
答案 1 :(得分:0)
或者这个:
[a[i] for i in range(len(a)) if b[i]]
答案 2 :(得分:0)
我知道问题是两个列表,并没有提到 numpy 。但是如果您考虑使用它,并且假设a和b是numpy数组,则映射操作变得微不足道:
a[b]
我冒昧地使用1000x元素对建议的选项进行基准测试:
import numpy
a = [1,2,3,4] * 1000
b = [True, True, False, True] * 1000
def question_fn():
l2_true = []
for el in range(len(a)):
if b[el] == True:
l2_true.append(a[el])
return l2_true
def suggestion_1():
return [v for i, v in enumerate(a) if b[i]]
def suggestion_2():
return [x for x,y in zip(a,b) if y]
x = numpy.array(a)
y = numpy.array(b)
def using_numpy():
return x[y]
python -m timeit -s 'import so' 'so.question_fn()'
1000 loops, best of 3: 453 usec per loop
python -m timeit -s 'import so' 'so.suggestion_1()'
10000 loops, best of 3: 203 usec per loop
python -m timeit -s 'import so' 'so.suggestion_2()'
1000 loops, best of 3: 238 usec per loop
python -m timeit -s 'import so' 'so.using_numpy()'
10000 loops, best of 3: 23 usec per loop
请注意, numpy 时序不包括转换为数组,否则会比所有其他建议的解决方案慢得多。但是,如果从一开始就使用numpy数组是一个选项,那么它可能是一个可行的解决方案。