美文网首页
删除序列相同元素并保持顺序

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

作者: limbo1996 | 来源:发表于2021-01-12 22:32 被阅读0次

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

    问题

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

    解决

    >>> 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}]
    
    
    

    相关文章

      网友评论

          本文标题:删除序列相同元素并保持顺序

          本文链接:https://www.haomeiwen.com/subject/vtbjaktx.html