如何实现含NaN数组的数字升序NaN后置排序?及相关疑问
含NaN数组的排序问题及解答
问题背景
需要对包含NaN的数组进行排序,要求数字按升序排列,NaN置于末尾:
const array = [5, 9, NaN, 3, 15];
期望得到的结果:
const expected = [3, 5, 9, 15, NaN];
先后尝试以下两种排序写法,均无法达到预期效果:
- 基于减法的排序逻辑:
const res = array.sort((a, b) => a - b);
- 基于比较运算符的排序逻辑:
const res = array.sort((a, b) => { if (a > b) return 1; if (b > a) return -1; return 0; });
同时存在疑问:为何以下代码中res1和res2的输出结果相同?
const array = [5, 9, NaN, 3, 15]; const res1 = array.sort((a, b) => a - b); const res2 = array.sort((a, b) => b - a); console.log(res1, res2);
正确的排序实现
要实现数字升序、NaN置于末尾的需求,必须在排序函数中专门处理NaN的特殊特性——NaN与任何值的比较结果都是false,与任何值做减法都会得到NaN,这会干扰默认排序逻辑。
正确的排序逻辑如下:
const array = [5, 9, NaN, 3, 15]; const res = array.sort((a, b) => { // 若a是NaN,将其排到后面 if (Number.isNaN(a)) return 1; // 若b是NaN,将b排到后面(即a排在前面) if (Number.isNaN(b)) return -1; // 正常数字按升序比较 return a - b; }); console.log(res); // 输出:[3, 5, 9, 15, NaN]
原写法失效原因
- 减法逻辑失效:当比较涉及NaN时,
a - b的结果为NaN,排序函数会将NaN视为0处理,导致NaN无法被正确移至末尾,位置随机。 - 比较运算符逻辑失效:
NaN > 任何值和任何值 > NaN的结果都是false,当比较包含NaN时,两个if条件都不触发,直接返回0,无法调整NaN的位置。
res1与res2结果相同的原因
数组的sort方法是原地排序——它会直接修改原数组本身,而非返回一个新数组。具体过程:
- 第一次调用
array.sort((a,b)=>a-b)时,原数组array已被修改,res1是原数组的引用。 - 第二次调用
array.sort((a,b)=>b-a)时,是在已经被修改过的数组基础上再次排序,res2同样指向原数组。 - 由于
res1和res2指向同一个数组对象,最终打印结果自然一致。
若要得到两个不同的排序结果,需先复制原数组,再分别排序:
const array = [5, 9, NaN, 3, 15]; // 通过扩展运算符复制数组,避免修改原数组 const res1 = [...array].sort((a, b) => a - b); const res2 = [...array].sort((a, b) => b - a); console.log(res1, res2); // 此时两个结果不同
内容的提问来源于stack exchange,提问作者underfrankenwood
相关产品推荐
相关产品推荐

