如何计算数组中两个有效数值间的零值并实现线性填充?
线性填充数组中的0值(基于前后有效数值插值)
需求:给定一个包含0值的数值数组,需要用相邻两个有效数值之间的线性差值填充所有0值。示例数组
arr = [10,0,0,16,17,0,23],期望输出[10,12,14,16,17,20,23]。以下是我当前的JavaScript实现代码,但无法得到正确结果,寻求可行解决方案:
let arr = [10,0,0,16,17,0,23] //required result [10,12,14,16,17,20,23] // here is my code const getValueIf = (item, index, array) => { const lastindex = array.length - 1; const zeroWithFirst = index !== 0 && item === 0; const zeroWithLast = index !== lastindex && item === 0; const firstZero = index === 0 && item === 0; if (firstZero) { return array[index] = ifZeroToNumber(array, index) ; } if (zeroWithFirst || zeroWithLast) { if (zeroWithFirst && !zeroWithLast) { return array[index - 1]; } if (!zeroWithFirst && zeroWithLast) { return array[index + 1] === 0 ? array[index + 2] : array[index + 1]; } array[index] = (ifZeroToNumber(array, index) - array[index - 1]) / 2 + array[index - 1]; return ( (ifZeroToNumber(array, index) - array[index - 1]) / 2 + array[index - 1] ); } else { return item; } }; const ifZeroToNumber = (array, index) => { let num = 0; for (let i = 1; i <= array.length; i++) { if (num === 0 && array[index + i]) { num = array[index + i]; } } if (!num) { num = array[index - 1]; } return num; }; let removeZero = arr.map((value, index) => getValueIf(value, index, arr) ); console.log(removeZero)
现有代码的问题
- 只处理了间隔1个0的场景,遇到多个连续0(比如示例里的前两个0)时计算逻辑失效
ifZeroToNumber函数无法正确定位后续的有效数值,当连续多个0时会出错- 插值逻辑简单粗暴,没有根据两个有效数之间的间隔数量计算正确的步长
- 使用
map时直接修改原数组,可能干扰后续的遍历计算
可行实现方案
核心思路是先找出所有非0的"锚点"(记录索引和对应值),再对每一对相邻锚点之间的0值做线性插值计算:
const linearFillZeros = (arr) => { // 收集所有非0的锚点 const anchors = arr.reduce((acc, val, idx) => { if (val !== 0) acc.push({ idx, val }); return acc; }, []); // 边界情况处理:没有锚点直接返回原数组,单个锚点则全填充该值 if (anchors.length === 0) return [...arr]; if (anchors.length === 1) return arr.map(() => anchors[0].val); const result = [...arr]; // 遍历每对相邻锚点,填充中间的0 for (let i = 0; i < anchors.length - 1; i++) { const start = anchors[i]; const end = anchors[i + 1]; // 计算步长:总差值除以间隔步数(比如10到16之间有2个0,步数是3) const step = (end.val - start.val) / (end.idx - start.idx); // 逐个填充中间的0 for (let j = start.idx + 1; j < end.idx; j++) { result[j] = start.val + step * (j - start.idx); // 如果需要整数结果,可改为:Math.round(start.val + step * (j - start.idx)) } } // 处理数组开头的连续0 if (anchors[0].idx > 0) { const firstVal = anchors[0].val; for (let j = 0; j < anchors[0].idx; j++) { result[j] = firstVal; } } // 处理数组结尾的连续0 if (anchors[anchors.length - 1].idx < arr.length - 1) { const lastVal = anchors[anchors.length - 1].val; for (let j = anchors[anchors.length - 1].idx + 1; j < arr.length; j++) { result[j] = lastVal; } } return result; }; // 测试示例 const arr = [10,0,0,16,17,0,23]; console.log(linearFillZeros(arr)); // 输出: [10, 12, 14, 16, 17, 20, 23]
实现说明
- 锚点收集确保能精准定位每一段需要插值的区间
- 步长计算根据两个有效数之间的间隔动态调整,适配任意数量的连续0
- 首尾的连续0会填充最近的有效数值,覆盖所有边界场景
- 不修改原数组,返回新的填充后数组,避免副作用
内容的提问来源于stack exchange,提问作者Ali Nawaz
相关产品推荐
相关产品推荐

