Python数据结构去重操作汇总【收藏版】


在 Python 中,去重是一个常见操作,特别是在处理数据结构时。以下是几种常见的数据结构的去重方法,包括列表、元组、集合和字典。此外,还会介绍嵌套数据结构的去重方法。

1.列表去重

1.1 使用集合去重

lst = [1, 2, 2, 3, 4, 4, 5]
unique_lst = list(set(lst))
print(unique_lst)

1.2 保持顺序去重

lst = [1, 2, 2, 3, 4, 4, 5]
unique_lst = []
seen = set()
for item in lst:
    if item not in seen:
        unique_lst.append(item)
        seen.add(item)
print(unique_lst)

2.元组去重

2.1 转换为集合去重

tup = (1, 2, 2, 3, 4, 4, 5)
unique_tup = tuple(set(tup))
print(unique_tup)

2.2 保持顺序去重

tup = (1, 2, 2, 3, 4, 4, 5)
unique_tup = []
seen = set()
for item in tup:
    if item not in seen:
        unique_tup.append(item)
        seen.add(item)
unique_tup = tuple(unique_tup)
print(unique_tup)

3 集合去重

集合本身不允许重复元素:

s = {1, 2, 2, 3, 4, 4, 5}
print(s)

4 字典去重

4.1 按键去重

d = {'a': 1, 'b': 2, 'c': 2, 'd': 3}
unique_d = {k: v for k, v in d.items()}
print(unique_d)

4.2 按值去重

d = {'a': 1, 'b': 1, 'c': 2, 'd': 3}
unique_d = {k: v for k, v in d.items() if list(d.values()).count(v) == 1}
print(unique_d)

5 类实例去重

5.1 使用集合去重

假设我们有一个 Person 类,我们可以通过定义 __hash____eq__ 方法来使类的实例可被集合去重:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __hash__(self):
        return hash((self.name, self.age))

    def __eq__(self, other):
        return (self.name, self.age) == (other.name, other.age)

    def __repr__(self):
        return f"Person(name={self.name}, age={self.age})"

persons = [Person('Alice', 30), Person('Bob', 25), Person('Alice', 30)]
unique_persons = list(set(persons))
print(unique_persons)

6 嵌套数据结构去重

6.1 嵌套列表去重

递归去重,保持嵌套结构的顺序:

def unique_nested_list(lst):
    seen = set()
    unique_lst = []
    for item in lst:
        if isinstance(item, list):
            item = tuple(unique_nested_list(item))
        if item not in seen:
            seen.add(item)
            unique_lst.append(item)
    return unique_lst

nested_lst = [[1, 2], [2, 3], [1, 2], [3, 4]]
unique_nested_lst = unique_nested_list(nested_lst)
print(unique_nested_lst)

6.2 嵌套列表去重的简便写法【常用】

nested_lst = [[1, 2], [2, 3], [1, 2], [3, 4]]
unique_lst = [list(t) for t in {tuple(x) for x in nested_lst}]
print(unique_lst)

内层集合推导:{tuple(x) for x in nested_lst} 将每个子列表 x 转换为元组并去重。
外层列表推导:[list(t) for t in unique_set] 将去重后的元组转换回列表。

6.3 嵌套字典去重

递归去重,包括字典的键和值:

def unique_nested_dict(d):
    seen = set()
    unique_dict = {}
    for k, v in d.items():
        if isinstance(v, dict):
            v = tuple(sorted(unique_nested_dict(v).items()))
        elif isinstance(v, list):
            v = tuple(unique_nested_list(v))
        if (k, v) not in seen:
            seen.add((k, v))
            unique_dict[k] = v
    return unique_dict

def unique_nested_list(lst):
    seen = set()
    unique_lst = []
    for item in lst:
        if isinstance(item, dict):
            item = tuple(sorted(unique_nested_dict(item).items()))
        elif isinstance(item, list):
            item = tuple(unique_nested_list(item))
        if item not in seen:
            seen.add(item)
            unique_lst.append(item)
    return unique_lst

nested_dict = {
    'a': {'b': 1, 'c': 2},
    'd': {'b': 1, 'c': 2},
    'e': {'f': 3}
}
unique_nested_dict = unique_nested_dict(nested_dict)
print(unique_nested_dict)

6.4 嵌套字典去重的简便写法【常用】

import json

nested_dicts = [
    {'a': 1, 'b': {'c': 2, 'd': 3}},
    {'a': 1, 'b': {'c': 2, 'd': 3}},
    {'a': 2, 'b': {'c': 3, 'd': 4}}
]

# 将字典转换为 JSON 字符串,然后去重
unique_dicts = list({json.dumps(d, sort_keys=True) for d in nested_dicts})
# 将 JSON 字符串转换回字典
unique_dicts = [json.loads(d) for d in unique_dicts]

print(unique_dicts)

解析

1.转换为 JSON 字符串:
使用 json.dumps(d, sort_keys=True) 将字典转换为 JSON 字符串,并且 sort_keys=True 确保字典中的键按顺序排列,从而确保相同的字典生成相同的字符串。
2.集合去重:
使用集合 {…} 对 JSON 字符串进行去重,因为字符串是不可变的,可以直接用来去重。
3.转换回字典:
使用 json.loads(d) 将去重后的 JSON 字符串转换回字典。

6.5 嵌套集合去重

处理嵌套集合时,利用 frozenset 来实现不可变集合的去重。

nested_sets = [{1, 2}, {2, 3}, {1, 2}, {4, 5}]
unique_sets = list(set(frozenset(s) for s in nested_sets))
print(unique_sets)

7 使用第三方库去重

7.1 Pandas去重

Pandas库在处理数据框时提供了强大的去重功能。

import pandas as pd

df = pd.DataFrame({'A': [1, 2, 2, 3], 'B': [4, 5, 5, 6]})
unique_df = df.drop_duplicates()
print(unique_df)

8 嵌套数据结构去重

8.1 使用 frozenset 处理嵌套列表

对于嵌套列表,可以利用 frozenset 来处理不可变集合的情况。

def unique_nested_list(lst):
    def make_frozenset(item):
        if isinstance(item, list):
            return frozenset(make_frozenset(sub_item) for sub_item in item)
        return item

    unique_set = set(make_frozenset(item) for item in lst)
    
    def make_list(item):
        if isinstance(item, frozenset):
            return [make_list(sub_item) for sub_item in item]
        return item

    unique_lst = [make_list(item) for item in unique_set]
    return unique_lst

nested_lst = [[1, 2], [2, 3], [1, 2], [3, 4]]
unique_nested_lst = unique_nested_list(nested_lst)
print(unique_nested_lst)

9 基于键值对的复杂字典去重

对于复杂的字典,可以通过自定义哈希和比较函数来处理。

def unique_complex_dict(dicts):
    class DictWrapper:
        def __init__(self, d):
            self.d = d
        
        def __hash__(self):
            return hash(frozenset(self.d.items()))
        
        def __eq__(self, other):
            return self.d == other.d
        
    unique_dicts = list(set(DictWrapper(d) for d in dicts))
    return [dw.d for dw in unique_dicts]

dicts = [
    {'a': 1, 'b': 2},
    {'b': 2, 'a': 1},
    {'a': 2, 'b': 3}
]
unique_dicts = unique_complex_dict(dicts)
print(unique_dicts)

10 复杂嵌套数据结构去重

结合各种数据结构处理复杂的嵌套情况。

def recursive_unique(data):
    if isinstance(data, list):
        return list(map(recursive_unique, set(map(tuple, data))))
    elif isinstance(data, dict):
        return {k: recursive_unique(v) for k, v in data.items()}
    elif isinstance(data, set):
        return set(map(recursive_unique, data))
    else:
        return data

nested_structure = {
    'a': [{'x': 1, 'y': 2}, {'x': 1, 'y': 2}, {'x': 3, 'y': 4}],
    'b': {frozenset([1, 2]), frozenset([1, 2]), frozenset([3, 4])}
}

unique_nested_structure = recursive_unique(nested_structure)
print(unique_nested_structure)

11 自定义类去重

为自定义类提供更加复杂的去重逻辑。

class CustomObject:
    def __init__(self, id, name, value):
        self.id = id
        self.name = name
        self.value = value
    
    def __hash__(self):
        return hash((self.id, self.name))
    
    def __eq__(self, other):
        return self.id == other.id and self.name == other.name
    
    def __repr__(self):
        return f"CustomObject(id={self.id}, name={self.name}, value={self.value})"

objs = [
    CustomObject(1, 'Alice', 100),
    CustomObject(2, 'Bob', 200),
    CustomObject(1, 'Alice', 300)
]
unique_objs = list(set(objs))
print(unique_objs)

拓展:字符串去重【不常用】

在Python中,可以通过多种方式对字符串进行去重。以下是几种常见的方法:

1 使用集合去重并保持顺序

def unique_string(s):
    seen = set()
    return ''.join(seen.add(c) or c for c in s if c not in seen)

s = "banana"
unique_s = unique_string(s)
print(unique_s)  # 输出: "ban"

2 使用集合去重但不保持顺序

s = "banana"
unique_s = ''.join(set(s))
print(unique_s)  # 输出可能是: "abn"(顺序不固定)

3 使用字典的 fromkeys 方法去重并保持顺序(Python 3.7+)

s = "banana"
unique_s = ''.join(dict.fromkeys(s))
print(unique_s)  # 输出: "ban"

4 使用 collections.OrderedDict 去重并保持顺序(适用于Python 3.6及以下版本)

from collections import OrderedDict

s = "banana"
unique_s = ''.join(OrderedDict.fromkeys(s))
print(unique_s)  # 输出: "ban"

5 使用列表解析去重并保持顺序

s = "banana"
unique_s = ''.join([c for i, c in enumerate(s) if c not in s[:i]])
print(unique_s)  # 输出: "ban"

6 使用Pandas去重

import pandas as pd

s = "banana"
unique_s = ''.join(pd.Series(list(s)).drop_duplicates().tolist())
print(unique_s)  # 输出: "ban"

这些方法中,前三种是最常用的,特别是第一种和第三种,能够保持字符的原始顺序。如果你对顺序没有要求,可以使用第二种方法,它更简单直接。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今晚务必早点睡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值