您可以使用OrderedDict按每个元组的第一个子元素对元素进行分组:
myList=[(1,2),(1,3),(1,4),(1,5),(2,6),(2,7),(2,8),(3,9),(3,10)]
from collections import OrderedDict
od = OrderedDict()
for a,b in myList:
od.setdefault(a,[]).append(b)
print(list(od.values()))
[[2, 3, 4, 5], [6, 7, 8], [9, 10]]
如果您真的想要元组:
print(list(map(tuple,od.values())))
[(2, 3, 4, 5), (6, 7, 8), (9, 10)]
如果你不关心元素出现的顺序,只想要最有效的分组方式,可以使用
collections.defaultdict。
from collections import defaultdict
od = defaultdict(list)
for a,b in myList:
od[a].append(b)
print(list(od.values()))
最后,如果您的数据按照您的输入示例排序,即有序的话,您可以简单地使用
itertools.groupby按每个元组的第一个子元素进行分组,并从分组的元组中提取第二个元素。
from itertools import groupby
from operator import itemgetter
print([tuple(t[1] for t in v) for k,v in groupby(myList,key=itemgetter(0))])
输出:
[(2, 3, 4, 5), (6, 7, 8), (9, 10)]
再次强调,groupby 只有在数据至少按第一个元素进行了排序后才能正常工作。
对于一个适当大小的列表,我们进行了一些计时:
In [33]: myList = [(randint(1,10000),randint(1,10000)) for _ in range(100000)]
In [34]: myList.sort()
In [35]: timeit ([tuple(t[1] for t in v) for k,v in groupby(myList,key=itemgetter(0))])
10 loops, best of 3: 44.5 ms per loop
In [36]: %%timeit od = defaultdict(list)
for a,b in myList:
od[a].append(b)
....:
10 loops, best of 3: 33.8 ms per loop
In [37]: %%timeit
dictionary = OrderedDict()
for x, y in myList:
if x not in dictionary:
dictionary[x] = []
dictionary[x].append(y)
....:
10 loops, best of 3: 63.3 ms per loop
In [38]: %%timeit
od = OrderedDict()
for a,b in myList:
od.setdefault(a,[]).append(b)
....:
10 loops, best of 3: 80.3 ms per loop
如果顺序很重要且数据已经排序,使用
groupby,如果需要将所有元素映射到
defaultdict中的元组,则它将更接近于
defaultdict方法。
如果数据未排序或您不关心任何顺序,那么除了使用
defaultdict方法外,您找不到更快的分组方式。