3

例如:

>>> a
[2, -4, -2, 4, -3, -1, 3, 4, 2, 2]

>>> unique(a)
[2, 3, 4, -2, -4, -3, -1]

它给了我一个值列表,每个值只出现一次,但我希望它也以与原始列表相同的顺序打印它们。

4

2 回答 2

6

Aset没有顺序,因此在将列表转换为集合后,迭代元素时产生的顺序是实现细节。

您可以使用OrderedDict来获得一些带有订单的设置行为:

>>> from collections import OrderedDict
>>> a = [2, -4, -2, 4, -3, -1, 3, 4, 2, 2]
>>> x = OrderedDict.fromkeys(a)
>>> list(x)
[2, -4, -2, 4, -3, -1, 3]
于 2013-10-10T21:07:32.220 回答
0

这是一种更快(虽然不太紧凑)的方法,它基本上迭代原始列表中的元素,检查它们是否还在set您要添加的元素中。可能会有一些细微的变化可以进一步加快我的方法:

def _order(orig):
    ordset = set()
    for x in orig:
        if x in ordset:
            continue
        ordset.add(x)
        yield x
def unique(orig):
    return list(_order(orig))

输出:

>>> unique(a)
[2, -4, -2, 4, -3, -1, 3]

基准测试

戳的答案

>>> import timeit
>>> setup = '''
a = [2, -4, -2, 4, -3, -1, 3, 4, 2, 2]
from collections import OrderedDict
def unique():
    x = OrderedDict.fromkeys(a)
    return list(x)
'''
>>> print (min(timeit.Timer('unique()', setup=setup).repeat(100, 1000)))
0.031305141204512665

上面的答案:

>>> import timeit
>>> setup = '''
a = [2, -4, -2, 4, -3, -1, 3, 4, 2, 2]
def _order(orig):
    ordset = set()
    for x in orig:
        if x in ordset:
            continue
        ordset.add(x)
        yield x
def unique(orig):
    return list(_order(orig))
'''
>>> print (min(timeit.Timer('unique(a)', setup=setup).repeat(100, 1000)))
0.0031761333803501657

这种方法快了近 10 倍。对于这样的小列表,差异可以忽略不计,Poke 的回答很棒。但是,如果您碰巧对大量列表执行此操作(例如,长 10000 倍),则差异为 75 秒与 5 秒。

于 2015-04-15T15:24:26.130 回答