You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

接收对象键参数适配多结构对象的排序函数排序异常问题

闪卡应用通用快速排序功能异常排查

需求说明

开发闪卡应用时,需要对卡组、卡片等不同类型的对象列表按字母序排序,希望复用同一套快速排序逻辑,无需为每类对象单独编写排序函数。计划将待排序对象数组、排序依据的属性键作为参数传入排序函数,但修改代码后无法得到正确的排序结果。

初始可运行代码(固定按question属性排序)

const pivot = (arr, start) => {
    let pivotVal = arr[start]['question'].toUpperCase();
    let swapIdx = start;
    for(let a = start + 1; a < arr.length; a++){
        if(pivotVal > arr[a]['question'].toUpperCase()){
            swapIdx++;
            swap(arr, swapIdx, a);
        }
    };
    swap(arr, start, swapIdx);
    return swapIdx;
}

const alphabetize = (arr, start = 0, end = arr.length - 1) => {
    if(start < end){
        let pivotIdx = pivot(arr, start);
        alphabetize(arr, start, pivotIdx - 1)
        alphabetize(arr, pivotIdx + 1);
    }
    return arr;
}

setCards(alphabetize(newCards, 0, cards.length - 1)); // useState hook调用

修改后支持自定义排序字段的异常代码

const pivot = (arr, start, comparand) => {
    let pivotVal = arr[start][`${comparand}`].toUpperCase();
    let swapIdx = start;
    for(let a = start + 1; a < arr.length; a++){
        if(pivotVal > arr[a][`${comparand}`].toUpperCase()){
            swapIdx++;
            swap(arr, swapIdx, a);
        }
    };
    swap(arr, start, swapIdx);
    return swapIdx;
}

const alphabetize = (arr, start = 0, end = arr.length - 1, comparand) => {
    if(start < end){
        let pivotIdx = pivot(arr, start, comparand);
        alphabetize(arr, start, pivotIdx - 1, comparand)
        alphabetize(arr, pivotIdx + 1, comparand);
    }
    return arr;
}

setCards(alphabetize(newCards, 0, cards.length - 1, 'question')); // useState hook调用

问题原因

核心错误:递归参数顺序错误

alphabetize函数的参数顺序为(arr, start = 0, end = arr.length - 1, comparand),你在处理右半区间的递归调用时,只传了3个参数,相当于把comparand赋值给了end形参,后续递归逻辑没有拿到正确的排序属性键,导致排序逻辑失效。
修改方法:补全递归调用的end参数即可

// 原错误写法
alphabetize(arr, pivotIdx + 1, comparand);
// 修改后正确写法
alphabetize(arr, pivotIdx + 1, end, comparand);

潜在优化点

  • 分区函数的循环范围不合理:当前pivot函数循环遍历整个数组,而快速排序分区只需处理当前[start, end]区间的元素,建议将循环条件改为for(let a = start + 1; a <= end; a++),避免重复操作已排序区间,同时避免边界异常。
  • 动态属性取值不需要用模板字符串包裹,arr[start][comparand]和arr[start][${comparand}]效果完全一致,直接使用前者即可减少不必要的字符串转换开销。
  • 调用排序函数时如果newCards是新生成的数组,建议end参数传newCards.length - 1,避免新数组和原cards数组长度不一致导致的边界错误。

内容的提问来源于stack exchange,提问作者SkyeWulff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 19:15:04