用平均值填充数组

时间:2018-05-05 06:14:29

标签: javascript jquery arrays

我想知道我在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"

中的空白

7 个答案:

答案 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;
&#13;
&#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)

试试此代码

&#13;
&#13;
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;
&#13;
&#13;

答案 3 :(得分:0)

您可以迭代稀疏数组并存储最后一个索引和值。如果找到间隙,则间隙将填充最后一个值和实际值的平均值。

&#13;
&#13;
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;
&#13;
&#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]));

一些想法:

  • 对findFirstNotUndefined的递归调用处于尾调用位置
  • findFirstNotUndefined应该是memoizable,(可能)对大洞有用
  • 平均周围可以写自由风格,但不是没有添加其他功能或导入一些像ramda这样的fp库
  • 修改averageAround的签名,例如(_, 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
  • 如果当前值头未定义,我们会递增增加孔的大小并保持最后一个非空值,以计算平均值
  • 在所有其他情况下,我们用平均值填充空洞,我们添加当前值,然后递归到剩余数组,将lastNotNull重置为head,将holeWidth重置为0,默认值为

我觉得最后一步可以在执行时间方面进行优化,但我喜欢它紧凑而清晰(如果已经适应递归)的事实

奖励:我喜欢这个洞充满Array.prototype.fill功能

的事实