Python中如何高效处理包含4千万个元素的列表去重

如题
主要问题:千万级别处理起来会不会崩溃?

主要是去重

谢谢


Python中如何高效处理包含4千万个元素的列表去重
43 回复

自己做一个然后试一下不就知道了


用集合(set)转换是最直接高效的方法,因为集合基于哈希表实现,去重和查找的平均时间复杂度是O(1)。

# 假设你的原始列表是 huge_list
huge_list = [...]  # 包含4千万个元素

# 去重操作
unique_items = list(set(huge_list))

如果顺序不重要,上面这行代码就够了。集合转换会自动去重,然后转回列表。

但要注意几个关键点:

  1. 内存消耗:同时存在原始列表和集合两个数据结构,内存占用会翻倍。4千万个元素如果都是整数,大概需要300MB内存(列表)+ 300MB内存(集合)。如果内存紧张,可以考虑分批处理。

  2. 保持顺序:如果需要保持元素首次出现的顺序,用字典:

from collections import OrderedDict

# Python 3.6+ 普通dict就保持插入顺序
unique_ordered = list(dict.fromkeys(huge_list))

# 或者用OrderedDict(兼容旧版本)
unique_ordered = list(OrderedDict.fromkeys(huge_list))
  1. 元素类型限制:集合要求元素必须是可哈希的(hashable)。列表、字典等可变类型不能放入集合。如果列表包含不可哈希元素,需要先处理或改用其他方法。

简单总结:用set()最快,要保序就用dict.fromkeys()。

得看业务情况啊,不知道你后续的处理是要做哪些操作,否则只是去重,最简单粗暴的转换为 set 就完事了

推荐用 64 位 Python,加内存就是了。

list(set(li)
崩溃了就是你电脑不行!(滑稽

既然都能打算一次性把 4000 个元素放到一个 list 里面操作,不如就直接再导入 Excel 去重:doge:。

这种建议直接上 MongoDB 然后设置索引唯一去重

内存里的操作怕啥,比数据库强多了,随便搞

In [4]: N = 10**8

In [5]: arr = np.random.randint(0, N, size=N)

In [6]: len(arr)
Out[6]: 100000000

In [7]: %timeit set(arr)
36 s ± 122 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

给你一个时间作参考。。。

先分段排序,然后去重。

几千万的数据,一台电脑运行,有可行性吗?

excel 处理不了百万以上的行数吧

看精度要求,不高的话布隆过滤器可以一试

几千万而已 洒洒水啦

首先,这 4 千万个元素肯定是要便利一遍的,除非你的数据有什么特殊的规律。
其次,要看这 4 千万存在哪,内存?文件?网络?
最后,如果没有优化空间不可避免的要对 4 千万数据过一遍那就看想优化内存还是想优化时间了,不过最快可能也就是楼上 8 楼给的。

4 千万 uint32,最大也就 40M 搞定了…… O ( N )操作而已

这样都不肯用 pandas 吗?

布隆过滤器

想了想, 好像不需要

千万,也就 MB 级别吧

数据都不说一下怎么分情况处理。

这种统一建议 list(set(data))

你也说了是行数,要是每个元素都写进去单个 cell 里面不就够啦。:doge:

不是,你也说一下你每条数据多大啊,每条数据 1kb 和每条数据 10mb 当然不一样

既然 4 千万个元素能放进数组里,说明你内存就够用,去重就是了,就看算法对内存的使用和耗费的 cpu 时间了。

4kw 个 int,160M,可以直接放内存。
设计一个分布尽可能均匀的散列函数(这一步不太确定我不是搞数学的。瞎拍一个 md5(obj)//4kw 的算法不知道效果怎么样?)
遍历每个 obj 求 hash,把 obj 的 index 放在对应的桶里。
如果桶里已有元素( hash 冲突),单独放在另一个冲突列表里。
对于冲突列表里的每个冲突 hash,遍历并精确对比每个 obj,从源数据集删除完全相同的 obj。

稍微注意一下 getObj(index)的 O(1)复杂度,理论上可以应对任意量的数据了。

#8 只替换最后一步

%timeit np.unique(arr)
11.4 s ± 401 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

看看 bitmap

bitmap 对于非数字型的元素无法支持, 还是用布隆过滤器吧

你这水平,处理什么都会崩溃
自己不会试验吗
要问人,又不说清楚细节

讨论这么多写个代码就这么难吗也没几行啊

想在内存跑的话,简单直接暴力的就是用 set, 推荐布隆过滤器;每个元素比较大的话可以考虑 mr,spark 或者其他分布式计算框架

首先你要清楚数据的特征啊 整形?浮点数?短字符串?超长字符串?数据分布?重复概率?这些都会影响去重的效率!!!
V2EX √
动手实践 ×

bloomfilter ?

excel 最大 100 万条记录吧。

试试 numpy 吧,python list 遍历会检查类型,每次都会。

#23
你这个就是 Hash Table 的思想,getObj(index) 是 O(1),但是求一遍 hash 还是得 O(n) 啊。

天天 4 千万,和每月,每年是有区别的。
但是,其实也没多大区别

Bloom Filter

list(set(item))

![]( https://i.loli.net/2019/07/15/5d2c746fe371343950.png) 粗略的感觉,耗时不到一秒… 也可能不到 0.5.

不好意思我的数太简单了 -__-

没有元素类型、数据大小信息,更没有电脑内存的信息,就直接问 Python 能不能,别人就只能瞎猜随便说了。

还有,千万不要用 C、C++、C#,甚至 Java 之类的语言的设计和使用经验来估计 Python 的内存用量,到时候如果楼主的电脑内存不够大,估计要死机。

回到顶部