维护序列项顺序的同时消除重复项
Posted jeffrey-yang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了维护序列项顺序的同时消除重复项相关的知识,希望对你有一定的参考价值。
在序列中,经常会碰到有重复项的情况,有时需要消除重复的项。
解决方案:使用set来构造无重复数据项类型。如:
a = [1, 5, 2, 1, 9, 1, 5, 10]
>>> set(a)
1, 2, 10, 5, 9
使用set构造数据后,原始的序列元素失去了当初的相对顺序。同时简单的使用set会有另一个问题:可哈希。我们知道,像list中包含list或dict等符合类型且作为set的构造函数参数进行set对象创建时,会有以下报错:
>>> c = ['x': 1, 'y': 2, 'x': 2, 'y': 3]
>>> set(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
为了解决上述问题,我们可以写一个函数先消除hash的序列的重复项消除,同时保持原有的子项的相对顺序。
def dedupe(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(dedupe(a))
[1, 5, 2, 9, 10]
通过构造一个生成器,并按原始顺序遍历items。每次遍历的时候,检查元素是否在集合容纳器中,若不在,则返回,并添加到set中。若已在set中,则跳过,继续遍历。
该函数仅对序列中所有子项全部可hash时有用。负责在进行集合add时会报错。
我们可以改进上述函数的实现,使其可以对不可hash(如dict)的对象进行特殊处理,如下:
def dedupe(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(dedupe(a, key=lambda d: (d['x'],d['y'])))
['x': 1, 'y': 2, 'x': 1, 'y': 3, 'x': 2, 'y': 4]
>>> list(dedupe(a, key=lambda d: d['x']))
['x': 1, 'y': 2, 'x': 2, 'y': 4]
>>>
提供一个类似max, min中的key函数参数,然后在实际调用时使用lambda匿名函数,实际val的值由匿名函数的返回值提供,若key不为None时。
>>>
以上是关于维护序列项顺序的同时消除重复项的主要内容,如果未能解决你的问题,请参考以下文章
在 Python 中,从列表中删除重复项以使所有元素都是唯一的*同时保留顺序*的最快算法是啥? [复制]