2013-03-18 72 views
0

返回true情况下,我有值的列表:映射布尔值的数组值的数组,在Python

a = [1,2,3,4] 

和布尔值的对应列表:

b = [True, True, False, True] 

我想将b映射到一个这样的位置,使得我得到所有值,使得它们在b中的对应值为'真'。因此,在这种情况下,答案是[1,2,4]

我能想到的唯一方法是循环遍历b的元素,获取索引为True,然后检索相应的索引一个。所以像这样:

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

您也可以使用['itertools.compress'](http://docs.python.org/2/library/itertools.html#itertools.compress)。例如:'list(itertools.compress(a,b))'。但我更喜欢列表理解解决方案。 – nymk 2013-03-18 19:29:32

回答

3

这里是一个列表理解应该做你想要什么:

[v for i, v in enumerate(a) if b[i]] 

另一种方法:

[x for x, y in zip(a, b) if y] 
+0

再次感谢@ F.J! – 2013-03-18 22:05:43

0

或者这样:

[a[i] for i in range(len(a)) if b[i]] 
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数组是一种选择,它可能是一个可行的解决方案。