我想知道我在Javascript中遇到的问题。我有一个场景,我需要填充数组中的空白与周围值的平均值。让我举个例子:
阵列: 1,2,3,4,5
在这种特殊情况下,我需要用周围数字的平均值来填补空白,即3.5。我认为这样做比较容易。
但是,当数组中有更多后续间隙时,我还需要确保这是有效的。
实施例: 1,2,3 ,,, 5
在这种情况下,两个间隙应填充3和5的平均值,结果为...... 3,4,4,5。
我被卡住的那一刻是我尝试迭代阵列并填补空隙,因为我用4填充了第一个间隙,但在那一刻,第二个间隙的周围数字是4(原始间隙)和5,所以我最终得到了
...... 3,4,4.5,5,......
这不是我需要的。
我使用jQuery迭代数组并从表中获取值。
这就是我加载数组的方式:
var list = [];
$('#mytable > tbody > tr').each(function() {
$this = $(this);
list.push(eval($this.find("input.number").val());
}
现在我需要迭代并填补" list"
中的空白答案 0 :(得分:4)
以下是一种可能的实施方式:
function fill(arr) {
while (arr.includes(undefined)) {
const startIndex = arr.findIndex(num => num === undefined);
const endIndex = arr.findIndex((num, i) => i >= startIndex && num !== undefined);
const avg = (arr[startIndex - 1] + arr[endIndex]) / 2;
for (let i = startIndex; i < endIndex; i++) arr[i] = avg;
}
return arr;
}
console.log(fill([1, 2, 3, , , 5, 6]));
console.log(fill([1, , , , , , 6]));
console.log(fill([1, , , , 3, 4, , , 6]));
&#13;
答案 1 :(得分:0)
你可以使用简单的迭代来做这样的事情。
function fillMissing(arr) {
// array for storing result
var res = [];
// iterate over the array
for (i = 0; i < arr.length; i++) {
// if undefined then call the function to calculate average or set the value
res[i] = arr[i] == undefined ? calculateAverage(arr, i) : arr[i];
}
return res;
}
function calculateAverage(arr1, i) {
// set preve and next value as nearest element
var prev = arr1[i - 1],
next = arr1[i + 1],
j = 1; // variable for iterating
// iterate to find out nearest defined value
// after the element
while (prev == undefined) { prev = arr1[i - ++j]; }
j = 1; // reset for next iteration
// iterate to find out nearest defined value
// before the element
while (next == undefined) { next = arr1[i + ++j]; }
//find average and return
return (prev + next) / 2;
}
console.log(fillMissing([1, 2, 3, , , 5, 6]));
console.log(fillMissing([1, 2, 3, , , 5, 6]));
console.log(fillMissing([1, , , , , , 6]));
console.log(fillMissing([1, , , , 3, 4, , , 6]));
答案 2 :(得分:0)
试试此代码
var x = "1, 2, 3, ,4, 5";
var y = "1, 2, 3, , , 5, 6";
var z = "1, , , , , , 6";
var q = "1, , , , 3, 4, , , 6";
function removeSpace(str) {
return str.replace(/ /g, "");
}
function splitString(str) {
return str.split(',');
}
function fill(str) {
var z = removeSpace(str);
var zPrime = splitString(z);
for (var i = 0; i < zPrime.length; i++) {
if (zPrime[i] == "") {
if (i + 1 < zPrime.length && zPrime[i + 1] != "") {
zPrime[i] = (Number(zPrime[i - 1]) + Number(zPrime[i + 1])) / 2;
} else {
var j = i + 1;
while (j < zPrime.length && zPrime[j] == "") j++;
var tp = (j < zPrime.length) ? Number(zPrime[j]) : 0;
var dn = (i - 1 > -1) ? Number(zPrime[i - 1]) : 0;
for (var k = i; k < j; k++) {
zPrime[k] = ((tp + dn) / 2) + '';
}
}
}
}
return zPrime;
}
console.log(fill(x));
console.log(fill(y));
console.log(fill(z));
console.log(fill(q));
&#13;
答案 3 :(得分:0)
您可以迭代稀疏数组并存储最后一个索引和值。如果找到间隙,则间隙将填充最后一个值和实际值的平均值。
function fill(array) {
array.reduce((last, v, i, a) => {
var j, avg;
if (last.index + 1 !== i) {
avg = (v + last.value) / 2;
for (j = 1; j < i - last.index; j++) {
a[last.index + j] = avg;
}
}
return { index: i, value: v };
}, { index: -1 });
return array;
}
console.log(fill([1, 2, 3, , , 5, 6]));
console.log(fill([1, , , , , , 6]));
console.log(fill([1, , , , 3, 4, , , 6]));
&#13;
答案 4 :(得分:0)
有趣的问题让我有点思考。
我的第一个想法是使用map
,但我发现它不考虑漏洞。修复了Array.from
将洞转换为undefined
我希望找到一个更简洁的解决方案,但我仍然会发布它
function fillMissing(a){
return Array.from(a).map((e,i)=> e !== undefined ? e : averageAround(i,a))
}
const averageAround = (index, array) => average(before(index, array), after(index, array))
const average = (a, b) => (a+b)/2
const before = findFirstNotUndefined.bind(null, -1)
const after = findFirstNotUndefined.bind(null, 1)
function findFirstNotUndefined(direction, index, array){
if (array[index] !== undefined) return array[index]
return findFirstNotUndefined(direction, index+direction, array)
}
console.log(fillMissing([1, 2, 3, , , 5, 6]));
一些想法:
(_, index, array)
,可以直接在地图中使用:Array.from(a).map(averageAround)
。即使它计算每个值((val + val)/2
)答案 5 :(得分:0)
有一种递归方式可以做到这一点,基本上它会计算两个值之间的空点,并将这些空白点之间的差异分开:
var arr = [1, , , , 3, 4, , , 6];
for( var i = 0; i < arr.length; i++ ){
if( arr[ i ] === undefined )
arr[ i ] = avg( arr[ i - 1 ], arr.slice( i + 1, arr.length ), 1 );
}
function avg( low, arr, recursion ){
if( arr[ 0 ] === undefined )
return avg( low, arr.slice( 1, arr.length ), recursion + 1 );
return low + ( ( arr[0] - low ) / ( recursion + 1 ) );
}
console.log( arr );
像魅力一样:
arr = [1, 2, 3, ,4, 5] => [1, 2, 3, 3.5, 4, 5]
arr = [1, 2, 3, , , 5, 6] => [1, 2, 3, 3.6665, 4.3333, 5, 6]
arr = [1, , , , 3, 4, , , 6] => [1, 1.5, 2, 2.5, 3, 4, 4.6667, 5.3334, 6]
答案 6 :(得分:0)
另一个功能递归版
const arr = [1,2,3,,,5,6]
function fill([head,...tail], lastNotNull, holeWidth = 0){
if (tail.length === 0 ) return head
if (head === undefined) return fill(tail, lastNotNull, ++holeWidth)
return Array(holeWidth).fill((lastNotNull+head)/2).concat(head).concat(fill(tail, head))
}
console.log(fill(arr))
说明:
fill
函数的第一个参数被解构为head和tail。 Head表示当前值和尾部下一个值
tail
空 - &gt;我们只返回head
我觉得最后一步可以在执行时间方面进行优化,但我喜欢它紧凑而清晰(如果已经适应递归)的事实
奖励:我喜欢这个洞充满Array.prototype.fill
功能