删除序列相同元素并保持顺序

删除序列相同元素并保持顺序

问题

在序列上保持元素顺序的同时删除重复的值

解决

>>> def dedup(items):
...     seen = set()
...     for item in items:
...         if item not in seen:
...             seen.add(item)
...     return seen
... 
>>> a = [1, 5, 2, 1, 9, 1, 5, 10]    
>>> list(dedup(a))
[1, 2, 5, 9, 10]

首先看错误的,上面代码虽然完成了去重,但是元素的位置发生了变化

下面是正确代码

>>> def dedup(items):
...     seen = set()
...     for item in items:
...         if item not in seen:
...             yield item
...             seen.add(item)
... 
>>> a = [1, 5, 2, 1, 9, 1, 5, 10]    
>>> list(dedup(a))
[1, 5, 2, 9, 10]

这里的方法仅适用于元素是可哈希的,而yield的作用就是返回迭代器。

可以将上面的函数改造一下看一下结果

def dedup(items):
    seen = set()
    for item in items:
        if item not in seen:
            yield item
            seen.add(item)
            print('a')
>>> list(dedup(a))
a
a
a
a
a
[1, 5, 2, 9, 10]

因为dedup函数带yield,所以它返回的是一个迭代器,我们可以用next()函数,分步运行便于理解

>>> c = dedup(a)  
>>> next(c)
1
>>> next(c)
a
5
>>> next(c)
a
2
>>> next(c)
a
9
>>> next(c)
a
10

c是一个迭代器,调用next()发现,每一次的函数运行只进行到yield字段,yield后面的在下次函数调用中完成。

如果想消除元素不可哈希的序列中的重复元素(比如字典),需要把代码再改一下

>>> def dedup(items, key = None):
...     seen = set()
...     for item in items:
...         val = item if key is None else key(item)
...         if val not in seen:
...             yield item
...             seen.add(val)
... 

a = [ {'x':1, 'y':2}, {'x':1, 'y':3}, {'x':1, 'y':2}, {'x':2, 'y':4}]
>>> list(dedup(a, key=lambda d: (d['x'],d['y'])))
[{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]


©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容