JavaScript自定义数组升序排序时部分元素丢失问题
问题说明
实现数组按数值从小到大升序排序的功能时,运行代码出现数组部分元素意外丢失的问题:执行测试用例[23, 2, 12, 4]时,控制台仅输出排序结果[2,4],其余元素均被遗漏。
问题复现代码
function findSmallest(numArr) { let smallestNumber = numArr[0] for (let i = 0; i < numArr.length; i++) { if (numArr[i + 1] < smallestNumber) { smallestNumber = numArr[i + 1] } } return smallestNumber; } function getSortedArray(arr) { let sortedArray = [] for (j = 0; j < arr.length; j++) { let smallest = findSmallest(arr) let smallestNumbmerIndex; for (let i = 0; i < arr.length; i++) { if (arr[i] === smallest) { smallestNumbmerIndex = i } } arr.splice(smallestNumbmerIndex, 1) sortedArray.push(smallest) } return sortedArray } let myArr = [23, 2, 12, 4] console.log(getSortedArray(myArr)) // 实际输出 => [2, 4],剩余元素丢失
故障原因
代码共有两处核心逻辑错误:
findSmallest函数存在数组越界访问:循环遍历到最后一个元素时,取numArr[i+1]会得到undefined,和数值比较时会触发隐式类型转换导致最小值判断错误。且该函数循环逻辑冗余,初始值已经取数组第一个元素,无需通过i+1偏移访问元素。getSortedArray外层循环判断条件错误:循环条件j < arr.length中,arr.length会随着内部splice删除元素动态减小,同时变量j持续递增,以初始长度为4的测试数组为例:第一次循环后数组长度变为3,第二次循环后数组长度变为2,第三次循环时j=2,判断2 < 2不成立直接退出循环,仅执行2次取值操作,自然无法拿到全部元素。另外外层循环的变量j未声明,会污染全局作用域。
修复后代码
function findSmallest(numArr) { let smallestNumber = numArr[0] // 从索引1开始遍历,避免越界 for (let i = 1; i < numArr.length; i++) { if (numArr[i] < smallestNumber) { smallestNumber = numArr[i] } } return smallestNumber; } function getSortedArray(arr) { let sortedArray = [] // 直接判断数组是否还有剩余元素,规避长度动态变化导致的循环提前终止问题 while (arr.length > 0) { let smallest = findSmallest(arr) let smallestNumberIndex = arr.indexOf(smallest) // 直接调用原生方法取索引,简化手写遍历逻辑 arr.splice(smallestNumberIndex, 1) sortedArray.push(smallest) } return sortedArray } let myArr = [23, 2, 12, 4] console.log(getSortedArray(myArr)) // 输出 [2, 4, 12, 23],符合升序预期
提示:上述代码是选择排序的手动实现,仅用于排查逻辑问题。生产环境实现数值数组升序排序,直接调用原生方法
arr.sort((a, b) => a - b)即可,不需要手动编写排序逻辑。
内容的提问来源于stack exchange,提问作者Misbah Ahmed
相关产品推荐
相关产品推荐

