如何在Python中对相似的值进行排序

4
我想知道如何对列表中的相似值进行排序,然后将这些相似值分成子列表。
例如:我需要一个函数,可能会执行以下操作:
def sort_by_like_values(list):
    #python magic

>>>list=[2,2,3,4,4,10]
>>>[[2,2],[3],[4,4],[10]]
OR
>>>[2,2],[3],[4,4],[10]

我阅读了排序API的相关资料,发现它可以很好地对列表中的内容进行排序,但无法将列表分成子列表。请问有哪个模块可以帮助我实现这一功能?


1
itertools.groupby() 对于这种情况非常好用。 - Li-aung Yip
5个回答

5

使用 itertools 模块中的 groupby 方法。

from itertools import groupby

L = [2, 2, 3, 4, 4, 10]

L.sort()
for key, iterator in groupby(L):
    print key, list(iterator)

结果:

2 [2, 2]
3 [3]
4 [4, 4]
10 [10]

需要注意的几个问题: groupby 函数需要对数据进行排序,才能按照指定的键进行分组,否则无法正常工作。此外,在继续处理下一组之前,必须先消耗完当前迭代器中的所有元素,因此请确保将 list(iterator) 存储到另一个列表或其他数据结构中。以下是一行代码即可得到所需结果:

>>> [list(it) for key, it in groupby(sorted(L))]
[[2, 2], [3], [4, 4], [10]]

干得好!不错。特别喜欢最后的列表推导式。 - NlightNFotis

2

请查看 itertools 模块,它有一个有用的 groupby 函数:

import itertools as i
for k,g in i.groupby(sorted([2,2,3,4,4,10])):
    print list(g)

....

[2, 2]
[3]
[4, 4]
[10]

你应该能够修改这个代码,以获取一个列表中的值。

2

如其他人所建议的一样,itertools.groupby是我首选的方法- 也可以使用collections.Counter获取键和频率,按键排序,然后根据频率扩展回去。

from itertools import repeat
from collections import Counter

grouped = [list(repeat(key, freq)) for key, freq in sorted(Counter(L).iteritems())]

1
使用列表推导式的 itertools.groupby() 可以正常工作。
In [20]: a = [1, 1, 2, 3, 3, 4, 5, 5, 5, 6]

In [21]: [ list(subgroup) for key, subgroup in itertools.groupby(sorted(a)) ]
Out[21]: [[1, 1], [2], [3, 3], [4], [5, 5, 5], [6]]

请注意,groupby() 返回一个迭代器列表,并且您必须按顺序使用这些迭代器。根据文档的说法:

返回的组本身是一个迭代器,它与 groupby() 共享底层可迭代对象。由于源是共享的,当 groupby() 对象被推进时,先前的组将不再可见。 因此,如果稍后需要那些数据,应将其存储为列表:


1

如果您不想使用itertools并且可以理解列表推导式,那么这也可以解决问题:

def group(a):
    a = sorted(a)
    d = [0] + [x+1 for x in range(len(a)-1) if a[x]!=a[x+1]] + [len(a)]
    return [a[(d[x]):(d[x+1])] for x in range(len(d)-1)]

这里是您的列表:a


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接