King丨小义 发表于 2022-7-17 11:50:35

python去重

arr = [{'a':2},{'a':5},{'a':2}]
当数组里面的元素是字典时,如何去重

临时号 发表于 2022-7-17 12:09:00

本帖最后由 临时号 于 2022-7-17 12:10 编辑

意思是去掉一个{'a':2}吗
如果是,那就这么写
arr = [{'a':2},{'a':5},{'a':2}]
res = []
for i in arr:
    if i not in res:
      res.append(i)
print(res)

King丨小义 发表于 2022-7-17 13:01:26

临时号 发表于 2022-7-17 12:09
意思是去掉一个{'a':2}吗
如果是,那就这么写

算法效率有点低吧,去重的时间复杂度是O(n^2), 并且一旦字典的键值对很多,算法就很慢了

King丨小义 发表于 2022-7-18 07:40:38

本帖最后由 King丨小义 于 2022-7-18 07:55 编辑

临时号 发表于 2022-7-17 12:09
意思是去掉一个{'a':2}吗
如果是,那就这么写

起码我能想到的,用map先将字典转字符串,然后使用set去重。字符串的比较要比字典的比较快多了。集合去重利用哈希表,算法复杂度能降低到O(n)

list(map(eval,set(map(str, arr))))

这段代码的复杂度体现在eval函数上,如果不考虑将字符串再转回字典(即最后要储存为json),代码还可进一步简化

list(set(map(str, arr)))

python爱好者. 发表于 2022-7-18 16:17:53

King丨小义 发表于 2022-7-18 07:40
起码我能想到的,用map先将字典转字符串,然后使用set去重。字符串的比较要比字典的比较快多了。集合去 ...

我其实也想到了用 set() 函数,但是应为其参数必须是不可哈希的,所以得先将每个元素转换为字符串,
但是你这样的出来的结果:
["{'a': 5}", "{'a': 2}"]
还有偏差,需要再遍历一次去掉双引号,因此效率反而落后

King丨小义 发表于 2022-7-18 21:01:47

本帖最后由 King丨小义 于 2022-7-18 21:46 编辑

python爱好者. 发表于 2022-7-18 16:17
我其实也想到了用 set() 函数,但是应为其参数必须是不可哈希的,所以得先将每个元素转换为字符串,
但 ...


键值对少的时候,这个方法确实速度反而慢(但由于少,再慢也慢不到哪去),但键值对一旦多了,这个优势就体现出来了。
func3确实有点问题,我一开始以为是json格式,后来仔细看发现有点区别,在这里写更多是体现没有eval函数下这行代码的速度(或许有更高效的模块能够代替eval,例如json库)。
list(map(json.loads,set(map(json.dumps, arr))))

King丨小义 发表于 2022-7-18 21:24:35

本帖最后由 King丨小义 于 2022-7-18 21:47 编辑

我应该说明一下应用场景的,这个应用场景是在爬虫中,由于某些原因,导致爬取的数据有重复。
list(map(eval,set(map(str, arr)))) 或者list(map(json.loads,set(map(json.dumps, arr))))
还有就是对于这行代码,理论上它存在一些问题,因为字典的键不一定按照相同顺序排列,所以会导致两个相同的字典被判定成不同的情况。
但是在绝大多数应用场景下,字典的键值对顺序都是在循环中写好的,一般顺序都是固定的,所以也可以适用。
页: [1]
查看完整版本: python去重