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"
这些方法中,前三种是最常用的,特别是第一种和第三种,能够保持字符的原始顺序。如果你对顺序没有要求,可以使用第二种方法,它更简单直接。
作者:今晚务必早点睡