python算法--001删除序列中的重复元素,并保持顺序不变【针对可哈希、不可哈希元素,有简单版和扩展版2种方法】

  python算法

【基本思想】

1、利用“(集合)中的元素,不可重复”,这一特性,逐一传递序列进行处理,确保序列的唯一性。

2、利用“生成器”,减少运行时间和空间。

额外收获:生成器的写法、lambda函数作为中间函数使用的方法、条件赋值表达式的写法。

 一、删除可哈希序列中的重复值

# 这种方法只能处理可哈希元素序列

def haxi(items):
    seen = set()
    for item in items:
        if item not in seen:
            yield item
            seen.add(item)
# 说明:
# 这里的seen.add(item)可以提前,
# 放入for循环中,结果并不会发生变化,
# 只是多执行了几次。

# seen.add(item),注意seen是集合类型,要求item必须是可哈希的。

# 以下是使用示例:

if __name__ == '__main__':
    ls = [5, 2, 1, 3, 5, 2, 9, 1, 12]
    print(list(haxi(ls)))

# 返回:[5, 2, 1, 3, 9, 12]

*集合中的值,要求可哈希,即不可变,因此只有以下4种:

1、数字 

2、字符串

3、元组

4、自定义类(需要实现__hash__方法)

因此,当序列中出现“字典、一般类”等对象时,需要“先将它们转换为【元组】

以下方法,是对上述方法的扩展,实现了:

处理不可哈希(列表、字典、未实现_hash_方法的自定义类)元素的能力。

二、功能增强--删除任意元素序列 

# 以下方法适用性更广,可以处理一切元素序列
# 实际使用中,需要注意lambda函数的用法
# 如果处理可哈希元素序列,则不需要传入参数key

def solution(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)

if __name__ == '__main__':
    ls_dic = [
        {'x': 2, 'y': 3},
        {'x': 1, 'y': 4},
        {'x': 2, 'y': 3},
        {'x': 2, 'y': 3},
        {'x': 10, 'y': 15}
    ]
    ls_list = [[2, 3],
               [1, 4],
               [2, 3],
               [1, 4],
               [10, 15]
               ]
    ls = [5,5,2,1,9,1,5,10]

print('原始字典序列是:\n', ls_dic)
print('处理后的字典序列是:\n', list(solution(ls_dic, key=lambda a: (a['x'], a['y']))))

print('原始列表序列是:\n', ls_list)
print('处理后的列表序列是:\n', list(solution(ls_list, key=lambda a: tuple(a))))

print('原始可哈希序列是:\n', ls)
print('处理后的列表序列是:\n', list(solution(ls)))

# 对于不可哈希元素序列,使用时,需要注意根据实际情况写lambda函数
# lambda 函数,实际是上传入了一个函数的引用
# 这个函数的作用,就是返回一个元组

补充:

关于可调用对象参数key,可以再参考:列表中的sort()函数

ls.sort(key = None , reverse = False)

这里使用key的意义与这里是一样的,都是考虑了【可哈希数据类型】和【不可哈希数据类型】

当使用【可哈希数据类型】时,直接调用 ls.sort(),即可。

当使用【不可哈希数据类型】时,需要使用可调用对象key,返回进行排序的【关键字】

比如:stu类中有sno、name、height,3个属性,需要按sno排序,使用时就需要传递key:

ls.sort(key = lambda x:x.stur)

  • 16
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值