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"

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

### Pandas中使用`drop_duplicates()`方法进行数据Python的Pandas库中,`drop_duplicates()`方法是一个非常强大的工具,用于从DataFrame或Series中删除复行。此方法可以基于所有列或指定列进行操作,并且可以选择保留首次出现、最后一次出现或者不保留任何复项。 以下是一些常见的用法和代码示例: #### 示例1:删除整个DataFrame中的复行 ```python import pandas as pd # 创建一个包含复值的 DataFrame data = {'Name': ['Alice', 'Bob', 'Alice', 'Eve'], 'Age': [25, 30, 25, 22], 'Score': [85, 90, 85, 88]} df = pd.DataFrame(data) # 对整个 DataFrame 进行 df_cleaned = df.drop_duplicates() print(df_cleaned) ``` 上述代码会删除完全相同的行,仅保留第一次出现的记录[^2]。 #### 示例2:基于某些列进行 如果只想根据特定列来判断是否复,可以通过`subset`参数指定这些列: ```python # 基于 'Name' 列进行 df_cleaned_subset = df.drop_duplicates(subset=['Name']) print(df_cleaned_subset) ``` 这样只会根据`Name`列的值来判断是否为复行,并保留第一次出现的记录[^2]。 #### 示例3:删除所有复项而不保留任何记录 有时需要完全移除所有复的记录,而不是保留其中一个。可以通过设置`keep=False`实现: ```python # 删除所有复项 data = pd.DataFrame({ 'a':[2,1,1,1,1,1,2], 'b':[1,3,2,4,1,1,5], 'c':[1,3,2,4,1,1,3], 'd':[1,3,2,4,1,1,8] }) data_del = data.drop_duplicates(keep=False) print(data_del) ``` 这里会将所有复的行都删除,不会保留任何复记录[^1]。 #### 示例4:提取复项 如果目标是从数据集中提取出所有复的行,可以通过两次调用`drop_duplicates()`来实现: ```python # 第一步: ,将非复数据丢弃 data1 = data.drop_duplicates(subset='a', keep=False, inplace=False) # 第二步: ,保留一组复数据 data2 = data.drop_duplicates(subset='a', keep='first', inplace=False) # 第三步: 合并并再次 result = data1.append(data2).drop_duplicates(subset='a', keep=False, inplace=False) print(result) ``` 这段代码首先移除了所有非复项,然后保留了一组复数据,最后通过合并和再次得到了所有复的记录[^4]。 #### 注意事项 当处理包含列表或其他复杂数据类型的列时,`drop_duplicates()`可能无法直接应用。此时需要先将列表转换为字符串形式再进行操作[^3]。 ```python import pandas as pd # 创建一个包含列表的 DataFrame df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [[1, 2], [1, 3], [2, 3], [1, 2]]}) # 将列表转换为字符串 df['B'] = df['B'].apply(lambda x: ','.join(map(str, x))) # 使用 drop_duplicates() 方法 df = df.drop_duplicates('B') print(df) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

今晚务必早点睡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值