JavaScript中先排序后去重需注意:数字排序必须用(a,b)=>a-b避免字符串比较,对象数组应先按关键字段排序再filter相邻去重,原始值可用Set优化性能,NaN需单独过滤。

JavaScript 中结合 sort 和去重,常见需求是:先按某种规则排序,再剔除重复项(尤其适用于对象数组或需要“保留首次出现的较大/较小值”等逻辑)。注意:sort 本身会修改原数组,且默认按字符串排序,需谨慎处理数字或自定义逻辑。
基础数字/字符串数组:先 sort 再 filter 去重
适用于简单类型,想按升序排列后只保留每个值第一次出现的位置:
const arr = [3, 1, 4, 1, 5, 9, 2, 6, 5]; const uniqueSorted = arr .slice() // 先拷贝,避免修改原数组 .sort((a, b) => a - b) // 数字升序 .filter((item, index, array) => index === 0 || item !== array[index - 1]); <p>// 结果:[1, 2, 3, 4, 5, 6, 9]
-
关键点:用
filter比较当前项与前一项是否相等,前提是已排序,重复项必然相邻 -
注意:不能直接对原数组
sort().filter(...)后赋值,因为sort返回的是原数组引用,但filter返回新数组 —— 这本身没问题;真正要防的是意外修改原数组,所以推荐slice()或展开运算符[...arr]
对象数组:按字段排序 + 基于 key 去重
例如按 age 升序,同时确保 id 不重复:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const users = [
{ id: 1, name: 'Alice', age: 30 },
{ id: 2, name: 'Bob', age: 25 },
{ id: 1, name: 'Alicia', age: 31 }, // id 重复
{ id: 3, name: 'Charlie', age: 25 }
];
<p>const uniqueByAgeThenId = users
.slice()
.sort((a, b) => a.age - b.age || a.id - b.id) // 先按 age 升序,age 相同则按 id 升序
.filter((item, index, array) => index === 0 || item.id !== array[index - 1].id);
-
说明:排序时用
a.age - b.age || a.id - b.id实现多级排序;去重时只比对id字段,因重复id必然相邻(前提是你排序逻辑能保证相同id尽量聚在一起,但更稳妥的做法是先按id排) -
更健壮写法:若目标是“每个 id 只留 age 最小的那个”,应先按
id分组或用Map预处理,而非依赖 sort + filter
用 Set + sort 实现简洁去重(仅限原始值)
如果只是去重并排序,不强调“排序后再去重”的语义,可先去重再排序,代码更清晰:
立即学习“Java免费学习笔记(深入)”;
const arr = [3, 1, 4, 1, 5, 9, 2, 6, 5]; const uniqueSorted = [...new Set(arr)].sort((a, b) => a - b); // 结果同上:[1, 2, 3, 4, 5, 6, 9]
-
优势:语义明确、性能好(
Set去重是 O(n),sort是 O(n log n),总体优于边排边滤) -
限制:
Set对对象无效({} !== {}),仅适用于字符串、数字、布尔等原始值
避免陷阱:sort 的默认行为和 NaN
arr.sort() 不传比较函数时,会把所有元素转成字符串再比较,导致 [10, 2, 1] 变成 [1, 10, 2];另外 NaN 在排序中可能被忽略或位置异常:
const arr = [10, 2, 1, NaN, 3]; arr.sort(); // [1, 10, 2, 3, NaN] —— 错误! arr.sort((a, b) => a - b); // [1, 2, 3, 10, NaN] —— NaN 仍在末尾,但至少数字有序
-
建议:只要涉及数字,必须传入比较函数
(a, b) => a - b -
处理 NaN:如需排除
NaN,可在filter中加!isNaN(item)判断

















