如何在条件上拆分列表?

时间:2012-12-31 10:44:52

标签: python

到目前为止,我没有找到按特定条件拆分列表的便捷方法,例如,我有一个记录列表:

 a = ((0,1),(1,0),(0,2),(1,0),(3,0),(4,0),(0,3),(1,5)....)

我想将内容拆分为2个列表

alist = []
blist = []
for x in a:
    if x[0] == 0:
        alist.append(x)
    elif x[0] == 1:
        blist.append(x)

不是很简洁。

写成列表推导:

aList = [x for x in a if x[0] == 0]
bList = [x for x in a if x[0] == 1]

列表推导通常适用于阅读和表现,但在这种情况下,列表必须重复两次。

有没有更好的方法来完成这项工作?

5 个答案:

答案 0 :(得分:6)

嗯,条件不同,难怪你需要两个循环。但如果你想牺牲一些可读性,

aList, bList = [[x for x in a if x[0] == i] for i in (0, 1)]

答案 1 :(得分:6)

添加一行将使循环更加简洁,代价是可读性(和FPness)。

alist = []
blist = []
bothlists = [alist, blist]
for x in a:
  bothlists[x[0]].append(x)

答案 2 :(得分:1)

如果你真的想让事情变得复杂,你可以从itertools导入一些函数来混淆你的可读解决方案:

from operator import itemgetter
from collections import defaultdict

d = defaultdict(list)

for key, value in itertools.groupby(a, itemgetter(0)):
    d[key].append(list(value))

这是输出:

>>> print d[0]
[[(0, 1)], [(0, 2)], [(0, 3)]]
>>> print d[1]
[[(1, 0)], [(1, 0)], [(1, 5)]]
>>> print d[4]
[[(4, 0)]]

此代码仅使用第一个元组中的值作为键将项目分组到字典中。它比你的代码更通用。

答案 3 :(得分:0)

我会使用filter,请参阅:http://docs.python.org/2/library/functions.html#filter

>>> a = ((0,1), (1,0), (0,2), (1,0), (3,0), (4,0), (0,3), (1,5))
>>> filter(lambda x: x[0] == 1, a)
((1, 0), (1, 0), (1, 5))

为避免冗余代码,您可以在迭代中收集条件,如下所示:

>>> fs = (lambda x: x[0] == 0, lambda x: x[0] == 1)
>>> for f in fs:
...     filter(f, a)
...
((0, 1), (0, 2), (0, 3))
((1, 0), (1, 0), (1, 5))

答案 4 :(得分:0)

字典可以更简洁。

alist, blist = [], []
for x in a:
    {0: alist, 1: blist}.get(x[0]).append(x)

这是一种灵活的模式,您可以扩展以涵盖其他情况。

例如,您可以添加更多选择。您还可以通过将 .get(x[0]) 更改为 .get(x[0], []) 来优雅地处理意外值。