美文网首页Python
从序列中删除重复元素且保持元素间顺序不变 --yield及集合的

从序列中删除重复元素且保持元素间顺序不变 --yield及集合的

作者: cook__ | 来源:发表于2018-09-28 22:07 被阅读95次

    首先明确2个概念:
    1、如果一个对象是可哈希的,那么在它的生存期内必须是不可变的。例如整数、浮点数、字符串、元组都是不可变的。
    2、集合中的元素是唯一的(可哈希的),但是顺序可变。

    先考虑序列中的元素是不可变

    直接使用set()转换:

    a = [1, 5, 2, 1, 9, 5, 10]
    set(a)
    Out[3]: {1, 2, 5, 9, 10}  # 虽去重了,但是元素的顺序变了
    

    迭代序列元素,并使用 yield语句,来保持元素的顺序:

    def dedupe(items):
        """ 在当序列中的元素是可hash的时候 """
        seen = set()
        for item in items:
            if item not in seen:
                yield item  # 使用生成器,返回唯一的元素
                seen.add(item)
    
    a = [1, 5, 2, 1, 9, 5, 10]
    list(dedupe(a))
    Out[5]: [1, 5, 2, 9, 10]
    
    如果序列的元素是不可哈希的呢?下面来实现更通用的解决方案
    def dedupe(items, key=None):
        """
        1、当序列中的元素是不可hash的,去除重复项
        2、使用set集合的目的是利用集合中的元素是唯一的这一特点,来保证返回值item中元素唯一,起到去重作用
        :param items:
        :param key: 指定一个函数用来将序列中的元素转换为可hash的类型
        :return:
        """
        seen = set()
        for item in items:
            val = item if key is None else key(item)
            if val not in seen:
                yield item  # 返回item
                seen.add(val)  # seen集合,确保相同的val值的item元素对象不会被返回
    
    # 元素是不可hash的
    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, y的value值去重
    Out[7]: [{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]
    list(dedupe(a, key=lambda d: d['x']))  # 根据x的value值去重
    Out[9]: [{'x': 1, 'y': 2}, {'x': 2, 'y': 4}]
    
    # 元素是可hash的
    a = [1, 5, 2, 1, 9, 5, 10]
    list(dedupe(a))
    Out[11]: [1, 5, 2, 9, 10]
    

    总结:
    1、可以使用集合和生成器来实现序列去重且保持元素顺序不变;
    2、生成器yield语句返回后,暂停挂起,执行后续操作后,再循环;
    3、dedupe()函数模仿了内置函数sorted()min()max()对key函数的使用方式。

    相关文章

      网友评论

        本文标题:从序列中删除重复元素且保持元素间顺序不变 --yield及集合的

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