简体   繁体   中英

Can anybody explain this snippet of code:

I have got this block of code and I could not get the r.concat part because concat usually is used on a whole array not on a single element of it.

function doubleOddNumbers(numbers) {
  return numbers.reduce((r, n) => n % 2 ? r.concat(n * 2) : r, [])
}

Here is the code annotated:

function doubleOddNumbers(numbers) {
  return numbers.reduce( // reduce iterates over numbers and passes an accumulator from iteration to iteration
    (r, n) => // the reducer function called for each element, r is the accumulator, n is the element
      n % 2   // if the element is odd
        ? r.concat(n * 2) // then append its double to the accumulator
        : r   // otherwise return the accumulator unchanged
  , [])       // start with an empty array for the accumulator
}

Here is the MDN documentation on reduce and concat .

I think the missunderstanding comes from this usage of reduce:

 [1, 2, 3].reduce((a, b) => a + b, 0); // 6

In this example, both the value of the array b , the accumulator a and the initial value 0 are numbers. But it doesn't have to be like this, the accumulator and the arrays values can have different types. If we change the line above to:

 [1, 2, 3].reduce((a, b) => a + b, "") // "123"

As the initial accumulator is an empty string, the first time reduce executes it will concat "" + 1 , which will result in "1" that gets passed to the next reduce step.

Now in your case, the initial accumulator value is an empty array.Therefore r will be an array, whilst n is a number. Now the reducer will either return r itself, or it will concatenate n * 2 to the array, which will also result in an array passed to the next reducer step.

  [1, 2, 3].reduce((acc, el) => acc.concat(el), []) 

That said, the code shown is just a complete missuse of the .reduce function. That you weren't able to understand the code does not mean that you are dumb, but it rather means that the code shown is badly written. I would write it as:

  numbers
     .filter(n => n % 2) // only.take odd numbers
     .map(n => n * 2) // double them

As "numbers" is an array (of numbers), you can just start with the specification of the Array.reduce function here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

Every reduce works like so:

arrayToReduce.reduce((memo, currentElement) => { /* operations using the currentElement that return the new memo value */}, initialValue);

What happens:

  1. You start with an initial value in memory (initialValue above) eg an empty array.

  2. For each element of the array to reduce (eg arrayToReduce above), you execute a function which receives the current memorized value ("memo" above) and the current element in the array. The function will examine the current element and will compute a new memorized value. Eg in your example, for odd numbers, you double the number and add it to the memorized array, then you return the memorized array; for even numbers you do nothing, so you return the memorized array unchanged.

  3. The last value returned by the function is the eventual result of the reduce operation ie the array containing the odd numbers doubled.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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