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

JS数组按升序值替换为对应索引问题及优化方案问询

解决数组元素替换为升序排列后对应索引的问题

问题根源

你遇到的问题本质是Array.indexOf()的局限性:它只会返回第一个匹配元素的索引,当数组存在重复值时,后续的重复元素会拿到错误的排名;如果元素值恰好等于某个索引值,还会和错误逻辑叠加导致结果混乱。

正确解决方案

核心思路是给每个元素绑定原始索引,排序后再根据原始索引映射回正确的排名,既能处理重复元素,也不会受元素值与索引值重合的影响。

代码实现

const nums = [32, -3, 62, 8, 121, -231, 62, 13];

// 1. 为每个元素绑定原始索引
const indexedElements = nums.map((value, originalIndex) => ({
  value,
  originalIndex
}));

// 2. 按元素值升序排序
indexedElements.sort((a, b) => a.value - b.value);

// 3. 生成结果数组:根据原始索引填充对应的排名(排序后的位置)
const result = new Array(nums.length);
indexedElements.forEach((element, rank) => {
  result[element.originalIndex] = rank;
});

console.log(result); // 输出:[4, 1, 5, 2, 7, 0, 6, 3]

测试问题数组

针对你提到的错误示例数组[32, -3, 62, 7, 121, -231, 62, 13, 0],运行上述代码会得到正确结果:

console.log(result); // 输出:[5, 1, 6, 3, 8, 0, 7, 4, 2]

其中-231对应的排名为0,完全符合预期。

原方案的修复思路(仅限特定场景)

如果坚持使用基于indexOf的逻辑,需要处理重复元素,但这种方式仅适用于允许重复值共享同一排名的场景,不符合你的示例要求:

const nums = [32, -3, 62, 8, 121, -231, 62, 13];
const sorted = [...nums].sort((a, b) => a - b);

// 创建值到排名的映射,跳过已处理的重复值
const rankMap = new Map();
sorted.forEach((val, idx) => {
  if (!rankMap.has(val)) {
    rankMap.set(val, idx);
  }
});

// 生成结果(重复值会共享同一排名)
const result = nums.map(val => rankMap.get(val));

注意:此方式会让示例中的两个62都返回5,不符合你需要的5和6的区分结果,因此第一种方案是最优解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:02:53