排序与去重需根据数据特征选择算法;快速排序平均性能优,归并排序稳定,堆排序省空间,小数组用插入排序;去重推荐Set或Map,原生方法通常最优。

在处理数组数据时,排序与去重是两个非常常见的操作。不同的算法在时间复杂度、空间消耗和实际运行效率上差异明显。本文将介绍几种主流的数组排序与去重方法,并从性能角度进行对比分析,帮助开发者根据场景选择最优方案。
常见排序算法及其效率
排序是去重的前提之一,尤其在使用基于比较的去重策略时尤为重要。以下是几种典型排序算法的表现:
- 快速排序(Quick Sort):平均时间复杂度为 O(n log n),最坏情况为 O(n²)。空间复杂度为 O(log n)。适合大多数场景,JavaScript 中 Array.prototype.sort() 在 V8 引擎中对大数组采用 Timsort,小数组使用快速排序变种。
- 归并排序(Merge Sort):稳定排序,时间复杂度始终为 O(n log n),但需要 O(n) 的额外空间。适合要求稳定性或大数据流排序。
- 堆排序(Heap Sort):时间复杂度 O(n log n),空间复杂度 O(1),但常数较大,实际性能不如快排。
- 插入排序(Insertion Sort):对小数组(n
数组去重的多种实现方式
去重方法的选择往往依赖于是否已排序、数据类型、内存限制等因素。
-
Set 去重(未排序数组):
利用 ES6 的 Set 数据结构自动去重,代码简洁:const unique = [...new Set(arr)];
时间复杂度 O(n),适用于原始类型数组,是目前最快的方法之一。 -
对象键值映射法(未排序):
使用对象或 Map 记录已出现元素:const unique = []; const seen = new Map(); for (const item of arr) { if (!seen.has(item)) { seen.set(item, true); unique.push(item); } }支持引用类型判断(需自定义 key),Map 比普通对象更安全高效。 -
双指针去重(已排序数组):
若数组已排序,可在 O(n) 时间内完成去重:arr.sort((a, b) => a - b); let j = 0; for (let i = 1; i < arr.length; i++) { if (arr[i] !== arr[j]) { arr[++j] = arr[i]; } } const unique = arr.slice(0, j + 1);空间复杂度低,适合内存受限环境。
综合性能对比与建议
不同组合在不同场景下的表现如下:
- 对于无序且数据量小(n [...new Set(arr)] 是最优选择,简洁高效。
- 当数组需要先排序再去重时,推荐“快排 + 双指针”组合,总时间复杂度约为 O(n log n),优于多次遍历。
- 若频繁插入查询且需动态维护唯一性,使用 Set 或 Map 结构比每次重新去重更高效。
- 处理对象数组去重时,可基于特定字段构造唯一 key,配合 Map 实现去重,例如:
const uniqueBy = (arr, keyFunc) => { const seen = new Map(); return arr.filter(item => { const key = keyFunc(item); if (seen.has(key)) return false; seen.set(key, true); return true; }); };
基本上就这些。排序与去重没有“万能”方案,关键是根据数据特征和性能要求合理搭配算法。现代 JavaScript 引擎优化充分,优先使用原生方法(如 Set、sort)通常是最优解,仅在特殊需求下才需手动实现底层逻辑。










