列表原序去重性能测试

对列表的去重很简单,set() 一下再 list() 回来就可以了,但是如果要保留原始列表的顺序呢?

举例,对 ["b", "b", "c", "a", "c", "b", "a", "b"] 这个列表进行原序去重,得到结果应该是 ['b', 'c', 'a']

有下面这几种写法:

二次排序

也就是对去重结果再按原列表 sort 一次:

def sort_1(list_in):
    return sorted(list(set(list_in)), key=list_in.index)

匿名函数

使用匿名函数将列表里不重复的元素累加到一个新列表中:

def sort_2(list_in):
    return reduce(lambda x, y: x if y in x else x + [y], [[], ] + list_in)

借用字典

有序字典

使用 OrderedDict 排序:

def sort_3(list_in):
    return list(collections.OrderedDict.fromkeys(list_in).keys())

defaultdict

类似的, 我们使用 defaultdict 进行排序:

def sort_4(list_in):
    return list(collections.defaultdict.fromkeys(list_in).keys())

直接使用 dict

在 python3.6 之前, dictkey 的顺序并不保证一定是插入顺序,所以只有在 python3.6 之后才可以直接用 dict 实现这个操作;

def sort_5(list_in):
    return list(dict.fromkeys(list_in).keys())

完整性能测试代码如下:

# !/usr/bin/env python
# encoding: utf-8

from timeit import repeat
from functools import reduce
from collections import defaultdict, OrderedDict

example = ["b", "b", "c", "a", "c", "b", "a", "b"]


def sort_1(list_in):
    return sorted(list(set(list_in)), key=list_in.index)


def sort_2(list_in):
    return reduce(lambda x, y: x if y in x else x + [y], [[], ] + list_in)


def sort_3(list_in):
    return list(OrderedDict.fromkeys(list_in).keys())


def sort_4(list_in):
    return list(defaultdict.fromkeys(list_in).keys())


def sort_5(list_in):
    return list(dict.fromkeys(list_in).keys())


if __name__ == '__main__':
    # time usage: t5< t4 < t3 < t2 < t1
    result = {}
    for i in range(1, 6):
        result['sort_{}'.format(i)] = repeat('sort_{}(example)'.format(i),
                                             'from __main__ import sort_{}, example'.format(i),
                                             number=1000000,
                                             repeat=5)
    for k, v in result.items():
        avg_v = round(sum(v) / len(v), 3)
        print(k, avg_v)

在我的苏菲婆上的结果仅供参考:

排序 平均时间
sort_1 1.477
sort_2 1.305
sort_3 0.957
sort_4 0.734
sort_5 0.698

可见,python3.6 之后 dict 是最好的原序去重办法,3.6 之前用 defaultdict 吧。

Lex Wayne
Lex Wayne
Python Knight & Go Padawan

You see, madness, as you know, is like gravity.