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

首先明确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函数的使用方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值