文章目录
一、为什么要和重复数据过不去?
程序员的日常就是和bug斗智斗勇(说多了都是泪💧),而数组去重堪称数据处理界的经典考题!想象一下你从数据库拿到10万条数据,结果发现60%都是重复项——这时候要是没掌握高效去重方法,你的CPU分分钟哭给你看!(别问我怎么知道的)
二、语言特攻队:各显神通
1. Python篇(版本≥3.7)
# 方法1:集合大法(顺序会乱!)
original = [2,5,2,8,5]
unique = list(set(original))
# 方法2:有序字典(Python3.7+保留插入顺序)
from collections import OrderedDict
unique = list(OrderedDict.fromkeys(original))
# 方法3:列表推导式(适合小数据量)
unique = []
[unique.append(x) for x in original if x not in unique]
踩坑预警🚨:
- 方法1简单粗暴但会打乱顺序(重要数据慎用!)
- 方法3的时间复杂度是O(n²)(超过1万条数据会卡成狗🐶)
2. JavaScript篇(ES6新姿势)
// 方法1:Set结构(ES6新特性)
let unique = [...new Set(array)];
// 方法2:filter+indexOf(兼容性好)
let unique = array.filter((item, index) => {
return array.indexOf(item) === index;
});
// 方法3:reduce大法(适合链式操作)
let unique = array.reduce((acc, current) => {
return acc.includes(current) ? acc : [...acc, current];
}, []);
实战技巧⚡:
- 方法1效率最高但需要ES6支持
- 方法2在IE浏览器会翻车🚗(别问,问就是血的教训)
3. Java篇(花式操作集合)
// 方法1:使用HashSet
List<Integer> list = Arrays.asList(2,5,2,8,5);
Set<Integer> set = new LinkedHashSet<>(list); // 保留顺序
List<Integer> unique = new ArrayList<>(set);
// 方法2:Stream API(Java8+)
List<Integer> unique = list.stream()
.distinct()
.collect(Collectors.toList());
性能对比📊:
- 数据量<1万:两者差别不大
- 数据量>10万:Stream API内存占用更优
4. C++篇(STL大显身手)
#include <vector>
#include <unordered_set>
vector<int> vec = {2,5,2,8,5};
unordered_set<int> s(vec.begin(), vec.end());
vector<int> unique(s.begin(), s.end());
// 保留原始顺序的版本
vector<int> unique;
unordered_set<int> seen;
for (int x : vec) {
if (seen.insert(x).second) {
unique.push_back(x);
}
}
冷知识❄️:
unordered_set的查找时间复杂度是O(1),比普通set快3-5倍!
5. PHP篇(数组函数三连)
// 最简单写法
$unique = array_unique($original);
// 保留键名的写法(注意!)
$unique = array_keys(array_flip($original));
// 处理关联数组
$unique = array_map("unserialize",
array_unique(array_map("serialize", $original)));
血泪史💔:
array_unique()对多维数组无效,遇到复杂结构记得先用serialize处理!
6. Ruby篇(优雅の哲学)
# 最简写法
unique = original.uniq
# 自定义去重规则
unique = original.uniq { |item| item[:id] } # 根据hash的某个键去重
黑科技🔮:
Ruby 2.4+版本支持带block的uniq方法,可以自定义去重逻辑
7. Go篇(切片操作的艺术)
func RemoveDuplicates(slice []int) []int {
seen := make(map[int]bool)
result := []int{}
for _, val := range slice {
if _, ok := seen[val]; !ok {
seen[val] = true
result = append(result, val)
}
}
return result
}
Go语言特色🚀:
利用map的键唯一性实现去重,时间复杂度O(n)效率直接起飞!
三、性能优化核弹级方案💣
当数据量突破百万级时,这些技巧能救你的命:
-
内存优化:使用bitmap(适合整数)
# Python示例 bitmap = 0 for num in nums: bitmap |= 1 << num unique = [i for i in range(bitmap.bit_length()) if (bitmap >> i) & 1] -
分布式处理:MapReduce分治思想
// 伪代码示例 const chunks = splitBigArray() // 分割数组 const results = await Promise.all(chunks.map(processChunk)) const finalResult = mergeResults(results) -
SIMD指令(C++专属黑魔法)
#include <x86intrin.h> // 使用AVX512指令集并行处理 // (需要特定CPU支持,慎用!)
四、防翻车指南(新手必看)
-
数据类型陷阱:
- 1和"1"在弱类型语言中是不同元素
- NaN在JavaScript中永远不等于自己
-
对象去重雷区:
const arr = [{id:1}, {id:1}]; console.log([...new Set(arr)]); // 两个对象都被保留! -
浮点数精度问题:
# Python示例 arr = [0.1+0.1+0.1, 0.3] print(set(arr)) # 输出两个元素!
五、终极总结(划重点)
| 语言 | 推荐方法 | 时间复杂度 | 顺序保留 |
|---|---|---|---|
| Python | OrderedDict | O(n) | ✔️ |
| JS | Set | O(n) | ❌ |
| Java | LinkedHashSet | O(n) | ✔️ |
| C++ | unordered_set+遍历 | O(n) | ✔️ |
| PHP | array_flip+keys | O(n) | ✔️ |
最后一句忠告💡:
不要为了炫技而使用复杂方法!处理10条数据用双重循环也没关系,但面对海量数据时,选错方法真的会原地爆炸💥(别问我怎么知道的)
736

被折叠的 条评论
为什么被折叠?



