删除序列相同元素并保持顺序
问题
在序列上保持元素顺序的同时删除重复的值
解决
>>> 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}]
网友评论