过滤两个相关列表的优雅方式

时间:2013-12-10 19:30:48

标签: python

我有一个简单的for循环。这是一个MWE:

a = [0.6767, -0.0386, 0.6767, 0.4621, 0.6052, 0.3906, 0.6052, 0.3906, 0.6052, 0.4621, 0.6052, 0.4621, 0.5337]
b = [3.6212, 1.5415, 3.4871, 1.8889, 3.3709, 2.078, 3.3012, 2.2236, 3.2265, 2.369, 3.1273, 2.522, 3.0076]
low_lim, high_lim = 0.5, 0.7

c, d = [], []
for indx,i in enumerate(a):
    if low_lim <= i <= high_lim:
        c.append(i)
        d.append(b[indx])

那么这个for循环的作用基本上是检查a中的某个项是否在某个范围内,如果是,那么它将该元素存储在c和相应的{ {1}}中的{1}}元素(即:具有相同索引的元素)。

如何更优雅/简洁地编写最后一段代码?

5 个答案:

答案 0 :(得分:4)

numpy是你的朋友:)

import numpy as np

a = np.array([0.6767, -0.0386, 0.6767, 0.4621, 0.6052, 0.3906, 0.6052, 0.3906, 0.6052, 0.4621, 0.6052, 0.4621, 0.5337])
b = np.array([3.6212, 1.5415, 3.4871, 1.8889, 3.3709, 2.078, 3.3012, 2.2236, 3.2265, 2.369, 3.1273, 2.522, 3.0076])
low_lim, high_lim = 0.5, 0.7

mask = (low_lim <= a) & (a <= high_lim)

c = a[mask]
d = b[mask]

cd = np.array([a[mask], b[mask]])
#now if you want a one dimensional array, flatten it.
cd = cd.flatten()

答案 1 :(得分:3)

使用zip配对和取消配对列表:

c,d = zip(*[(ia,ib) for (ia, ib) in zip(a,b) if low_lim <= ia <= high_lim])

此处需要splat运算符*。可以展开生成器表达式,但为了便于阅读,我在这里使用了列表推导。

答案 2 :(得分:1)

与Marcin的答案非常相似,但使用索引。如果您需要为两个以上的数组执行此操作,enumerate(a)可能比使用zip(a,b,c,d,..)更有效:

c,d = zip(*((a[i],b[i]) for i, x in enumerate(a) if low_lim <= x <= high_lim))

答案 3 :(得分:0)

for i, j in itertools.izip(a, b):
    if low_lim <= i <= high_lim:
        c.append(i)
        d.append(j)

答案 4 :(得分:0)

使用zip做同样的事情:

c, d = [], []
for a_elem, b_elem in zip(a, b):
    if low_lim <= a_elem <= high_lim:
        c.append(a_elem)
        d.append(b_elem)

如果可以制作元组列表而不是两个列表,那么

cd = [(a_elem, b_elem)
      for a_elem, b_elem in zip(a,b)
      if low_lim <= a_elem <= high_lim]