【问题标题】:How can I get average number in an array contain string and number如何获得包含字符串和数字的数组中的平均数
【发布时间】:2021-09-25 20:59:42
【问题描述】:

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

这里是测试用例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"。我怎样才能摆脱它并找到总和以获得平均数?

【问题讨论】:

  • 我做了一个sn-p。您需要返回过滤到控制台记录它
  • '...但它仍然有字符串 "57"' - 你为什么期望 .filter() 更改 str 中元素的类型(即一个可怕的名字)?
  • 注意filter()实际上并没有转换元素,它只是测试它是否可以。
  • @mplungjan "...只有数字,但仍然有字符串 "57"" - 返回 filtered 对实际问题有何影响?
  • @pilchard 即使这样,它也会拒绝像 0 这样的值或接受像 "1" 这样的值。

标签: javascript unit-testing tdd


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    映射和过滤

    注意我把变量名 str 改成了 arr 因为它不是字符串。

    我测试类型以及数字是否是有限的并添加了其余的计算

    代码现在返回预期的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}`) 

    【讨论】:

      【解决方案3】:

      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);
      

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

      【讨论】:

        【解决方案4】:

        您可以使用reduce 和内部回调使用typeof 来检查元素是否为非数字。累加器对象由总计、计数和平均值三个键组成。

        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]));

        【讨论】:

        • 看起来你只解析已经是数字的数字。你不想做相反的事情吗?如果它是一个数字,只需添加它。如果没有,尝试解析,成功则添加。
        • @Henrik 实际上根本不需要解析。上次编辑后忘记删除parse
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多