我有两个清单:
a = [-1, 2, 3]
b = ['a', 'b', 'c']
a
和b
中的元素数量始终相同。
我希望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 :(得分: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']
答案 1 :(得分:2)
我认为它可能是最短的:
filter(lambda x:x[0]>0, zip(a,b))
答案 2 :(得分:1)
您可以使用“zip-filter-unzip”策略:
说明步骤:
>>> [(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])
答案 3 :(得分:0)
你可以分两步完成。它不是“短”但绝对简单和干净。
b = [b[i] for i in xrange(len(b)) if a[i] > 0]
a = [x for x in a if x > 0]
答案 4 :(得分:0)
一些功能工具可以在一行中完成,非常好。:
anew, bnew = map(lambda x: list(x), zip(*filter(lambda z: z[0] > 0, zip(a, b))))
答案 5 :(得分: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