将主列表中的类似项目分组,并根据分组项目创建新列表

时间:2012-12-20 17:35:16

标签: python list

我正在尝试从一个主列表创建几个新列表,其中新列表包含来自主列表的类似项目。具体来说,我有一份巴士路线清单。这是一个示例数据集:

[u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line', u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line']

大多数公交线路有一个入站(IB)和一个出站(OB)项目(有些有多个IB和OB,有些只有一条路由,b / c它们是循环路由)。最后,我想在地图软件中合并IB和OB路线(我已经知道该怎么做了)......

我最初创建了文件名,因此前5个字符代表总线路径,无论它是IB还是OB。因此,我可以根据前5个字符对相似的项目进行分组。例如,当我写:

for route in routes:
    print route[0:5]

我明白了:

>>> 
Bus04
Bus04
Bus15
Bus15

如何将与Bus04Bus04以及Bus15Bus15相关的文件“分组”到新列表中,以便我得到:

[u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line'][u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line']作为单独的列表?

我正在考虑循环遍历每个项目的内容,查看每个项目的前五个字符,然后创建一个新列表,每个新的五个字符项出现(并将该项添加到新列表)或检查列表是否已存在并将类似项附加到其中。

我很难在代码中写出来,所以非常感谢任何帮助!

4 个答案:

答案 0 :(得分:6)

我会使用collections.defaultdict

import collections

L = [u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line', u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line']
d = collections.defaultdict(list)
for elem in L:
    d[elem.split('_')[0]].append(elem)
print(dict(d))

这会产生:

{u'Bus04': [u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line'],
 u'Bus15': [u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line']}

与目前提出的其他一些解决方案不同,无论条目在输入列表中的显示顺序如何,这都有效。

答案 1 :(得分:3)

您可以将itertools.groupby与自定义键功能结合使用,例如lambda x: x[0:5]

这是一个演示,为您提供静态列表(即不仅仅是生成器):

>>> import itertools
>>> lst = [u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line', u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line']
>>> [(key, list(val)) for key, val in itertools.groupby(lst, lambda x: x[0:5])]
Out[9]:
[(u'Bus04', [u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line']),
 (u'Bus15', [u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line'])]

答案 2 :(得分:2)

import collections

lists = collections.defaultdict(list)
for item in masterlist:
    lists[item[:5]].append(item)

答案 3 :(得分:1)

您可以将groupby与lambda键功能配合使用。

from itertools import groupby
results = groupby(data, key=lambda x: x[0:5])

>>> for item, values in results:
>>>     print item, list(values)
Bus04 [u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line']
Bus15 [u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line']

正如NPE在他的解决方案中所提到的,原始列表必须是一个排序列表。

但是,如果你只需要一次处理一个条目,这个解决方案非常有效,因为生成器只生成一个值,然后等待下一个值准备好使用。