如何对数字数组中的零序列进行插值填充?
基于非零邻值的序列零值插值填充方案
需求说明
给定数字序列:
let sequence = [ 0, 0, 0, 0, 0, 12, 64, 9, 6, 0, 0, 0, 25, 79, 57, 13, 39, 0, 0, 7, 7, 0, 0, 0, 0, 0, 49, 0 ];
需要用非零邻值替换所有零值,预期输出:
let output = [ 12, 12, 12, 12, 12, 12, 64, 9, 6, 10.75, 15.5, 20.25, 25, 79, 57, 13, 39, 28.3333, 17.6666, 7, 7, 14, 21, 28, 35, 42, 49, 49 ];
填充规则:
- 开头无左侧邻值的零序列,全部填充为右侧第一个非零值
- 末尾无右侧邻值的零值,填充为左侧非零值
- 两侧均有非零邻值的零序列,按线性插值填充
现有代码实现
const interpolateValues = (array, index0, index1, left, right) => { let n = index1 - index0 + 1; let step = (right - left) / (n + 1); for(let i = 0; i < n; i++){ array[index0 + i] = left + step * (i + 1); } } const findZerosSequences = (array) => { var counter = 0; var index = 0; var result = []; for (let i = 0; i < array.length; i++) { if (array[i] === 0) { index = i; counter++; } else { if (counter !== 0) { result.push([index - counter + 1, index]); counter = 0; } } } if (counter !== 0) { result.push([index - counter + 1, index]); } return result; } let sequence = [ 0, 0, 0, 0, 0, 12, 64, 9, 6, 0, 0, 0, 25, 79, 57, 13, 39, 0, 0, 7, 7, 0, 0, 0, 0, 0, 49, 0 ]; // 找到所有连续零的区间:[[0,4], [9, 11], [17, 18], [21, 25], [27, 27]] let zeroes = findZerosSequences(sequence); for(let i = 0; i < zeroes.length; i++){ let lf = sequence[zeroes[i][0] - 1]; let rf = sequence[zeroes[i][1] + 1]; if(lf !== undefined && rf !== undefined && lf > 0 && rf > 0){ interpolateValues(sequence, zeroes[i][0], zeroes[i][1], lf, rf); } } console.log(sequence); let output = [ 12, 12, 12, 12, 12, 12, 64, 9, 6, 10.75, 15.5, 20.25, 25, 79, 57, 13, 39, 28.3333, 17.6666, 7, 7, 14, 21, 28, 35, 42, 49, 49 ];
完整优化方案
现有代码未处理首尾无单侧邻值的场景,以下是覆盖所有边界情况的完整实现:
const interpolateValues = (array, index0, index1, left, right) => { const n = index1 - index0 + 1; const step = (right - left) / (n + 1); for (let i = 0; i < n; i++) { array[index0 + i] = left + step * (i + 1); } }; const fillWithValue = (array, index0, index1, value) => { for (let i = index0; i <= index1; i++) { array[i] = value; } }; const findZerosSequences = (array) => { const result = []; let start = null; for (let i = 0; i < array.length; i++) { if (array[i] === 0) { if (start === null) { start = i; } } else { if (start !== null) { result.push([start, i - 1]); start = null; } } } // 处理末尾的连续零 if (start !== null) { result.push([start, array.length - 1]); } return result; }; let sequence = [ 0, 0, 0, 0, 0, 12, 64, 9, 6, 0, 0, 0, 25, 79, 57, 13, 39, 0, 0, 7, 7, 0, 0, 0, 0, 0, 49, 0 ]; const zeroRanges = findZerosSequences(sequence); for (const [start, end] of zeroRanges) { const leftVal = sequence[start - 1]; const rightVal = sequence[end + 1]; if (leftVal === undefined) { // 开头零序列,用右侧非零值填充 fillWithValue(sequence, start, end, rightVal); } else if (rightVal === undefined) { // 末尾零序列,用左侧非零值填充 fillWithValue(sequence, start, end, leftVal); } else if (leftVal !== 0 && rightVal !== 0) { // 两侧有非零值,线性插值填充 interpolateValues(sequence, start, end, leftVal, rightVal); } } console.log(sequence); // 输出与预期output一致
优化说明
- 新增
fillWithValue函数,统一处理单侧填充逻辑,代码更简洁 - 重构
findZerosSequences函数,用start变量追踪连续零的起始索引,逻辑更清晰 - 遍历零区间时,分三种场景处理,覆盖所有边界情况
- 使用
for...of循环遍历零区间,可读性更强
内容的提问来源于stack exchange,提问作者toowren
相关产品推荐
相关产品推荐

