5

到目前为止,我还没有找到一种方便的方法来按某些条件拆分列表,例如,我有一个记录列表:

 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]

列表推导通常有利于阅读和性能,但在这种情况下,列表必须迭代两次。

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

4

5 回答 5

6

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

aList, bList = [[x for x in a if x[0] == i] for i in (0, 1)]
于 2012-12-31T10:49:42.287 回答
6

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

alist = []
blist = []
bothlists = [alist, blist]
for x in a:
  bothlists[x[0]].append(x)
于 2012-12-31T10:59:32.187 回答
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)]]

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

于 2012-12-31T11:03:53.267 回答
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))
于 2012-12-31T14:19:55.220 回答
0

dict 可以更简洁。

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

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

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

于 2021-01-05T04:34:43.783 回答