如何分组列表中的元素?

时间:2018-06-05 15:06:34

标签: python list sorting

我有一个python列表:

['AM43',
 'AM22',
 'AM51',
 'AM43',
 'AM22',
 'AM51',
 'AM43',
 'AM22',
 'AM51']

我希望输出成为一个列表:

['AM43',
 'AM43',
 'AM43',
 'AM22',
 'AM22',
 'AM22',
 'AM51',
 'AM51',
 'AM51']

我尝试了sort(),但这也重新安排了顺序。我不希望这样。我希望输出与输入列表的顺序相同。

4 个答案:

答案 0 :(得分:4)

您可以创建一个存储每个值第一次出现的索引的dict,并使用dict执行排序:

lst = ["AM43", "AM22", "AM51", "AM43", "AM22", "AM51", "AM43", "AM22", "AM51"]

ix = {k: i for i, k in reversed(list(enumerate(lst)))}
res = sorted(lst, key=ix.get)
# ['AM51', 'AM51', 'AM51', 'AM22', 'AM22', 'AM22', 'AM43', 'AM43', 'AM43']

编辑:@ emsimposon92提供了一个2通线性时间解决方案,可实现如下:

from collections import Counter

ctr = Counter(lst)
visited = set()
res2 = list()
for x in lst:
    if x in visited:
        continue
    res2.extend([x] * ctr[x])
    visited.add(x)

答案 1 :(得分:2)

您可以为每个唯一编号创建一个列表,然后根据原始输入顺序将它们连接起来。

答案 2 :(得分:1)

根据Yakym Pirozhenko的回答,要获得适当的订单,您需要在构建索引词典时反向枚举lst

lst = ["AM43", "AM22", "AM51", "AM43", "AM22", "AM51", "AM43", "AM22", "AM43"]

ix = {k: i for i, k in zip(range(len(lst), -1, -1), reversed(lst))}

res = sorted(lst, key=ix.get)

答案 3 :(得分:1)

以下是使用collections.Counteritertoolstoolz.unique的解决方案。请注意,最后一个使用第三方库,但源代码只是itertools unique_everseen recipe

from collections import Counter
from itertools import repeat, chain
from toolz import unique

lst = ['AM43', 'AM22', 'AM51', 'AM43', 'AM22',
       'AM51', 'AM43', 'AM22', 'AM51']

c = Counter(lst)
uniques = unique(lst)

res = list(chain.from_iterable(repeat(u, c[u]) for u in uniques))

res

['AM43', 'AM43', 'AM43',
 'AM22', 'AM22', 'AM22',
 'AM51', 'AM51', 'AM51']