简体   繁体   English

对数组求和的函数(包括数字作为字符串)

[英]Function that sums array numbers (including numbers as strings)

I have a function that needs to sum all numbers in an arrays, if those numbers are strings '1', '2' the function needs to sum those too. 我有一个函数需要对数组中的所有数字求和,如果这些数字是字符串'1','2',该函数也需要求和。

I have written a function and tried parsing the numbers but it doesn't work. 我已经写了一个函数并尝试解析数字,但它不起作用。 basically, it needs to sum up all numbers. 基本上,它需要总结所有数字。 Can you do it without using reduce ? 你可以不使用reduce吗? I need a simple solution or a solution with .map Where is my mistake? 我需要一个简单的解决方案或解决方案.map我的错误在哪里?

  function sumArrNums(arr) { let count = 0; arr.forEach(el => typeof el == 'number' ? count+= el : ''); return count; } console.log(sumArrNums(['1', '2', 5,5,5, '3'])) 

Your ternary operator is doing nothing when the element is a string, you can use Number(el) (or unary + ) to convert elements to numbers (strings will be converted, and numbers will remain numbers, so there is no need for type checking): 当元素是一个字符串时,你的三元运算符什么都不做,你可以使用Number(el) (或一元+ )将元素转换为数字(字符串将被转换,数字将保留数字,因此不需要进行类型检查):

 function sumArrNums(arr) { let count = 0; arr.forEach(el => count += Number(el)); return count; } console.log(sumArrNums(['1', '2', 5, 5, 5, '3'])) 

You can use isNaN to check if the number or string can be parsed to string or not, and than add values 您可以使用isNaN来检查数字或字符串是否可以解析为字符串,而不是添加值

Here + before el does implicit conversion from string to number 这里+之前el从字符串到数字的隐式转换

 function sumArrNums(arr) { let count = 0; arr.forEach(el => count += !isNaN(el) ? +el : 0); return count; } console.log(sumArrNums(['1', '2', 5, 5, 5, '3', {}, '1a', [] ])) 

I'd like to post a "meta"-answer, pointing at some archetypal mistakes made by you and other posters and frequently seen in other code reviews. 我想发布一个“meta”-answer,指出你和其他海报上的一些原型错误,并经常在其他代码评论中看到。

Mistake 1: unary + 错误1:一元+

Unary plus seriously hurts readability, especially in combination with other operators. 一元加上严重损害了可读性,特别是与其他运营商合并。 Please do your readers (including your a few months older self) a favor and use the Number function - this is what it's for: 请你的读者(包括你的几个月大的自己)一个忙,并使用Number功能 - 这是它的用途:

+a + +b   // 👎 wtf?

Number(a) + Number(b) // 👍 copy that

Apart from readability, Number(x) is identical to +x in every way. 除了可读性之外, Number(x)在各方面都与+x相同。

Mistake 2: not checking for NaN s 错误2:没有检查NaN

Number conversions can fail, and when they fail, they return a NaN and NaN s are sticky, so this will return NaN despite valid numbers being present in the array: 数字转换可能会失败,当它们失败时,它们会返回NaN并且NaN是粘性的,所以尽管数组中存在有效数字,但这将返回NaN

[1, 2, 'blah'].reduce((a, b) => Number(a) + Number(b)) // 👎 =NaN

This will be better (in the context of summation, NaN can be considered 0 ): 这样会更好(在求和的情况下, NaN可以被认为是0 ):

[1, 2, 'blah'].reduce((a, b) => (Number(a) || 0) + (Number(b) || 0)) // 👍 =3

Mistake 3: not checking for empty values 错误3:不检查空值

Unfortunately, Number is broken in javascript. 不幸的是, Number在javascript中被破坏了。 For "historical reasons" it returns 0 when given null or an empty string. 对于“历史原因”,当给定null或空字符串时,它返回0 For the summation function it doesn't matter, but it will bite you once you decide to use similar code for multiplication. 对于求和函数来说无关紧要,但是一旦你决定使用相似的代码进行乘法,它就会咬你。

Mistake 4: reduce with no initial value 错误4:减少没有初始值

array.reduce(func) looks tempting, but unfortunately it doesn't work with empty arrays array.reduce(func)看起来很诱人,但不幸的是它不适用于空数组

[].reduce((a, b) => a + b) // 👎 TypeError: Reduce of empty array with no initial value

so consider the init mandatory: 所以考虑init强制性:

[].reduce((a, b) => a + b, 0) // 👍 returns 0

Mistake 5: wrong iteration method 错误5:错误的迭代方法

The choice between iteration methods ( forEach/map/filter/reduce ) is tough sometimes, but this simple set of rules should help in most cases: 迭代方法( forEach/map/filter/reduce )之间的选择有时很难,但这个简单的规则集应该在大多数情况下有所帮助:

  • use map to convert a number of things to the same number of other things 使用map将许多东西转换为相同数量的其他东西
  • use filter to convert a number of things to a lesser number of the same things 使用filter将许多东西转换为相同数量的东西
  • use reduce to convert a number of things to one other thing 使用reduce将许多东西转换为另一种东西
  • do not use forEach 不要使用forEach

For example, this: 例如,这个:

result = [];
array.forEach(item => result.push(do_something(item))) // 👎

is an "antipattern" and should actually be map : 是一个“反模式”,实际上应该是map

result = array.map(do_something) // 👍

Similarly, this 同样,这个

result = 0;
array.map(item => result = result + item)) // 👎

should be 应该

result = array.reduce((res, item) => result + item, 0) // 👍

Putting it all together 把它们放在一起

Our assignment basically consists of three parts: 我们的任务基本上由三部分组成:

  • convert all elements in the array to numbers 将数组中的所有元素转换为数字
  • remove those that couldn't be converted 删除那些无法转换的内容
  • sum the rest 其余的总结

For the first step we use map , then filter , then reduce : 对于第一步,我们使用map ,然后filter ,然后reduce

let sumNumbers = a => a
    .map     (x => Number(x))        // convert to numbers
    .filter  (x => !Number.isNaN(x)) // remove NaN's
    .reduce  ((s, x) => s + x, 0)    // sum

On a more advanced note, with a couple of helpers we can also write this "point-free", without arrow functions: 更高级的说明,有几个助手,我们也可以写这个“无点”,没有箭头功能:

let not = fn => x => !fn(x);
let add = (x, y) => x + y;

let sumNumbers = a => a
    .map(Number)
    .filter(not(Number.isNaN))
    .reduce(add, 0)

Use unary + operator to convert your strings to numbers: 使用一元+运算符将字符串转换为数字:

 const sumArrNums = arr => arr.reduce((sum, num) => sum + +num, 0) console.log(sumArrNums(['1', '2', 5,5,5, '3'])) 

Your code is okay, you just need to ensure that you coerce the strings to number. 你的代码没问题,你只需要确保你强制字符串编号。 There are lots of ways to do that , in your case you might use the unary + : 很多方法可以做到这一点 ,在你的情况下你可以使用一元+

 function sumArrNums(arr) { let count = 0; arr.forEach(el => { count += +el; }) return count; } console.log(sumArrNums(['1', '2', 5,5,5, '3'])) 

and yes , this is one of the few really solid use cases for reduce : 是的 ,这是为数不多的真正用于reduce用例之一:

 function sumArrNums(arr) { // NOTE: Assumes at least one entry! More below... return arr.reduce((a, b) => +a + +b); } console.log(sumArrNums(['1', '2', 5,5,5, '3'])) 

Note there we're coercing both arguments to the callback, since on the first call they'll be the first two entries in the array (after that, the first argument will be the previously returned value, a number, but using + on it is a no-op so it's fine). 请注意,我们正在强制回调两个参数,因为在第一次调用时它们将是数组中的前两个条目(之后,第一个参数将是先前返回的值,一个数字,但在其上使用+是一个无操作,所以很好)。

That code assumes that arr will have at least one entry. 该代码假定arr至少有一个条目。 If it doesn't, reduce will fail because if you don't provide an initial value for the accumulator and there aren't any elements in the array, it doesn't have any value to return. 如果没有, reduce将失败,因为如果您没有为累加器提供初始值并且数组中没有任何元素,则它没有任何返回值。 If you want to return 0 , the simplest thing is to provide the initial value, which also means you don't have to apply + to the accumulator: 如果要返回0 ,最简单的方法是提供初始值,这也意味着您不必将+应用于累加器:

 function sumArrNums(arr) { return arr.reduce((acc, value) => acc + +value, 0); } console.log(sumArrNums(['1', '2', 5,5,5, '3'])) 

If you want to return something else (like NaN ) for the case where the array has no entries, you probably want to branch: 如果要在数组没有条目的情况下返回其他内容(如NaN ),则可能需要分支:

 function sumArrNums(arr) { return !arr.length ? NaN : arr.reduce((a, b) => +a + +b); } console.log(sumArrNums(['1', '2', 5,5,5, '3'])) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM