如何获得包含字符串和数字的数组中的平均数

How can I get average number in an array contain string and number

我正在编写一个函数来通过数组包含数字和字符串的测试。

这里是测试用例average-numner.test.js:

var average = require("./get-average");

test("Average", function() {
  var numbers = [4, "-", 8, 11, "hello", "57", 0, 2];
  var expected = 5;

  var output = average(numbers);

  expect(output).toEqual(expected);
});

这是我写的函数 average-number.js:

// the input is an array of numbers and strings
// return the average of all the numbers
// be sure to exclude the strings
function averageNumbers(str) {
  let sum = 0;
  let newArr = [];
  var filtered = str.filter(function(item) {
    return parseInt(item);
  });
  return filtered;
}

console.log(averageNumbers([4, "-", 8, 11, "hello", "57", 0, 2]));

//    module.exports = averageNumbers;

我得到了只有数字的新数组,但它在我的 filtered 数组中仍然有字符串 "57"。我怎样才能摆脱它并找到总和以获得平均数?

映射和过滤

注意,我将变量名 str 更改为 arr,因为它不是字符串。

我测试了类型和数字是否有限,并添加了剩余的计算

现在的代码returns预期的5

// the input is an array of numbers and strings
// return the average of all the numbers
// be sure to exclude the strings
function averageNumbers(arr) {
  const filtered = arr.filter(item => typeof item === 'number' && isFinite(item))
  const sum = filtered.reduce((a,b) => a+b)
  return +parseFloat(sum/filtered.length).toPrecision(12); // this can be ugly
}

console.log(averageNumbers([4, "-", 8, 11, "hello", "57", 0, 2]));
console.log(averageNumbers([3, "-", 4, 11, "hello", "57", 0, 2, 3]));

只是一个 reduce 返回一个对象来查看子部分

// the input is an array of numbers and strings
// return the average of all the numbers
// be sure to exclude the strings
const averageNumbers = arr => {
  const averageObject = arr.reduce((acc,item,i) => {
    if (typeof item === 'number' && isFinite(item)) {
      acc.sum+=item;
      acc.nofItems++;
    }  
    if (i===arr.length-1) acc.average = acc.sum/acc.nofItems;
    return acc;
  },{sum:0,nofItems:0, average:0})
  return averageObject;
}  

const ave1 = averageNumbers([4, "-", 8, 11, "hello", "57", 0, 2]);
console.log(`Average of ${ave1.nofItems} numeric items was ${ave1.average}. The sum was ${ave1.sum}`) 
const ave2 = averageNumbers([3, "-", 4, 11, "hello", "57", 0, 2, 3]);
console.log(`Average of ${ave2.nofItems} numeric items was ${ave2.average}. The sum was ${ave2.sum}`) 

filter 只检查给定元素的条件是否为真,如果是则保留。但它保留了原始值,而不是谓词函数的输出。如果您只想对数字求和,这应该可行:

var filtered = str.filter(function (item) {
    return parseInt(item);
  }).map(item => parseInt(item));

但是,如果一个数字被解析为 0,它将被认为是假的,过滤器将丢弃它。这对于计算总和是可以的,因为 0 没有区别,但如果你想保留它,你可以这样做:

const filtered = str.map(item => parseInt(item))
    .filter(item => item !== NaN);

这将尝试解析所有值,并仅保留成功解析的值,包括现有整数。

function averageNumbers(arr) {
  var filter = arr.filter(item => typeof item === 'number');
  var sum = filter.reduce((acc, n) => acc + n, 0);
  return sum / filter.length;
}

console.log(averageNumbers([4, "-", 8, 11, "hello", "57", 0, 2]));

//    module.exports = averageNumbers;

这给了你预期的 5

您可以使用 reduce 并在内部回调中使用 typeof 来检查元素是否为数字。 accumulator 对象由三个键组成,total,count 和 average。

function averageNumbers(c) {
  return c.reduce(function(a, b) {
    "number" === typeof b && (a.total += b, a.count += 1, a.average = a.total / a.count);
    return a;
  }, {
    total: 0,
    count: 0,
    average: 0
  }).average;
};

console.log(averageNumbers([4, '-', 8, 11, 'hello', '57', 0, 2]));