阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

我来教你Python字典组成的数组去重

78次阅读
没有评论

共计 2006 个字符,预计需要花费 6 分钟才能阅读完成。

导读 因为使用 set 去重的前提是该对象为不可变对象,而字典是可变对象,因此无法直接使用该方法去重。那么怎么解决这个问题呢?

你知道吗?如果数组是字典组成的,直接对数组内的字典采用 set 的方式进行去重,会报错:
我来教你 Python 字典组成的数组去重

test = [{"a": 1}, {"a": 1}, {"a": 3}, {"b": 4}]
test = list(set(test))
>>> TypeError: unhashable type: 'dict'

因为使用 set 去重的前提是该对象为不可变对象,而字典是可变对象,因此无法直接使用该方法去重。

那么怎么解决这个问题呢?有三个办法。

1. 使用 reduce 方法

reduce() 函数会对参数序列中元素进行累积。

比如:

from functools import reduce
def add(x, y) :            # 两数相加
    return x + y

print(reduce(add, [1,2,3,4,5])) # 计算列表和:1+2+3+4+5
# 15

上述写法也能用 lambda 函数简化为:

from functools import reduce
print(reduce(lambda x, y: x+y, [1,2,3,4,5])) # 使用 lambda 匿名函数
# 15

因此,我们自己编写一个函数进行数组内的字典去重:

from functools import reduce

data = [{"a": 1}, {"a": 1}, {"a": 3}, {"b": 4}]
result = []
def unduplicate(result, data):
    if data not in result:
        result = result + [data]
    return result

for i in data:
    result = unduplicate(result, i)

print(result)
# [{'a': 1}, {'a': 3}, {'b': 4}]

稍显复杂,如果使用 reduce 函数和 lambda 函数,代码能简化很多:

def delete_duplicate(data):
    func = lambda x, y: x + [y] if y not in x else x
    data = reduce(func, [[], ] + data)
    return data

print(delete_duplicate(data))
# [{'a': 1}, {'a': 3}, {'b': 4}]

当然,我也能一行写完这个功能:

data = reduce(lambda x, y: x + [y] if y not in x else x, [[],] + data)

只不过有可能会被打死在工位上,所以不建议这么干。

2. 奇怪的技巧

就如文章开头提到的,字典之所以不能用 set 去重,是因为它是可变对象。

但是 … 如果我们把它变成不可变对象呢?

data = [{"a": 1}, {"a": 1}, {"a": 3}, {"b": 4}]
def delete_duplicate(data):
    immutable_dict = set([str(item) for item in data])
    data = [eval(i) for i in immutable_dict]
    return data
print(delete_duplicate(data))
# [{'a': 1}, {'a': 3}, {'b': 4}]

没错,这能成。

遍历字典,将每个子项变成字符串存放到数组中,再通过 set 函数去重。
通过 eval 函数,将去重后的数组里的每个子项重新转化回字典。
如此 Python,怎能不好玩?

高效的方式
上面讲了两种骚操作,其实都不太建议在实际工作中使用。

一个原因是真的太骚了,怕被打趴在工位上。

另一个原因是,它们在应对较大数据量的时候,性能不太行。

下面是最正统的方式:

data = [dict(t) for t in set([tuple(d.items()) for d in data])]
# data:
# [{'a': 1}, {'b': 2}]

其实和第二种方式一样,是将数组内的每个字典转成元组,也就是不可变对象,再使用 set 进行去重。去重完毕后再使用 dict 函数将元组重新组成字典对。

但是,这种方法对于字典内还有字典的数据结构是不适用的,因此对于字典对里还有字典情况的去重,比如:

data2 = [{"a": {"b": "c"}}, {"a": {"b": "c"}}]

这种情况我建议使用第二种方式去重:

data2 = [{"a": {"b": "c"}}, {"a": {"b": "c"}}]def delete_duplicate_str(data):
    immutable_dict = set([str(item) for item in data])
    data = [eval(i) for i in immutable_dict]
    return data
print(delete_duplicate_str(data2))
# [{'a': {'b': 'c'}}]

怎么样,这三种方式你都学会了吗?

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-07-24发表,共计2006字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中