2014-03-06 11 views
4

我有两个列表:有条件地从两个列表中选择元素的简便方法?

a = [-1, 2, 3] 
b = ['a', 'b', 'c'] 

元素的数量在ab都是一样的。

我想保留a中的所有元素都是正数,并且对应的元素为b

一个简单的方法是

anew = [] 
bnew = [] 
for i in xrange(len(a)): 
    if a[i] > 0: 
     anew.append(a[i]) 
     bnew.append(b[i]) 

或类似

tmp = zip(*[(a[i], b[i]) for i in xrange(len(a)) if a[i]>0]) 
a = tmp[0] # The original a and b need not to be kept. 
b = tmp[1] 

我不知道是否有这样做的任何更短和更清洁的(没有任何临时变量)的方式。某种就地删除将是完美的,但如果我在循环中使用del a[i], b[i],删除一个元素后索引将会出错。

编辑:如果有什么选择包括两个列表,例如,如果条件变为

if a[i] > 0 and b[i] > 0

也许在这种情况下,必须使用一个临时变量?

+0

',但如果我用一个德尔[I],B [i]于一个回路,该指数将是一个element.'这是什么意思的删除后错了,你是不是也保持每个数的指数? –

+0

我的意思是,如果我使用C风格的循环,如:for xrange(len(a))中的i:如果a [i] <0:del a [i],b [i],则它不起作用。 – FJDU

+0

如果ai> = 0]'anew = [[ai,b [a.index(ai)]]如何? –

回答

2

我认为这可能是最短:

filter(lambda x:x[0]>0, zip(a,b)) 
+0

你忘了解压缩;-) – mgilson

+1

谢谢!你的答案的一点点编辑给出了我正在寻找的解决方案:a,b = zip(* filter(lambda x:x [0]> 0,zip(a,b))) – FJDU

+0

这里是赢家FJDU :),I几乎投票赞成JackGibbs – Melug

6

如果使用numpy,有一个很巧妙的方法:

In [117]: a = np.array([-1, 2, 3]) 
    ...: b = np.array(['a', 'b', 'c']) 

In [119]: a[a>0] 
Out[119]: array([2, 3]) 

In [120]: b[a>0] 
Out[120]: 
array(['b', 'c'], 
     dtype='|S1') 

如果没有numpy,您可以使用列表理解与条件语句:

In [121]: a = [-1, 2, 3] 
    ...: b = ['a', 'b', 'c'] 

In [122]: print [i for i in a if i>0] 
[2, 3] 

In [124]: print [v for i, v in enumerate(b) if a[i]>0] 
['b', 'c'] 
0

你可以做的两个步骤。这不是'短',但绝对简单和干净。

b = [b[i] for i in xrange(len(b)) if a[i] > 0] 
a = [x for x in a if x > 0] 
0

一些功能的工具可以在一行中做到这一点,相当不错:

anew, bnew = map(lambda x: list(x), zip(*filter(lambda z: z[0] > 0, zip(a, b)))) 
+1

我不认为lambda是必要的,是吗?你不能只用'list'吗? – mgilson

1

您可以使用“拉链式过滤器解压”的策略:

龙虎斗步骤:

>>> [(aa, bb) for aa, bb in zip(a, b) if aa > 0] 
[(2, 'b'), (3, 'c')] 
>>> zip(*[(aa, bb) for aa, bb in zip(a, b) if aa > 0]) 
[(2, 3), ('b', 'c')] 

最终结果:

>>> aaa, bbb = zip(*[(aa, bb) for aa, bb in zip(a, b) if aa > 0]) 
>>> aaa 
(2, 3) 
>>> bbb 
('b', 'c') 

正如你所看到的,我给了你一对元组 - 不是一对列表。在很多应用程序中,这并不重要,但是如果是这样,转换不会太困难;-)

这也扩展到覆盖两个列表都需要大于0的元素的情况:

aaa, bbb = zip(*[(aa, bb) for aa, bb in zip(a,b) if aa > 0 and bb > 0]) 
0

如果元素的顺序并不重要,对你,那么你可以用它为负电流元交换的最后一个元素。以下是我的想法的代码。

l = len(a) 
i = 0 
while i < l: 
    print i,l 
    while a[i] < 0: 
     a[i] = a[-1] 
     b[i] = b[-1] 
     a.pop() 
     b.pop() 
     global l 
     l = len(a) 
    i = i+1 


print a 
print b 
相关问题