Reduce() in depth

后端 未结 3 657
再見小時候
再見小時候 2021-01-22 01:31

In ES5, the new array method reduce(). I am wondering if someone can explain more in depth.

相关标签:
3条回答
  • 2021-01-22 01:56

    The method you pass into .reduce takes parameters previous_returned_value, current_iteration_item, current_iteration_index, context_array

    This means that each time it is called, the first argument is the return value from the previous invocation

    The initial value is what is passed in only the very first time.

    You can read the MDN docs about it here


    return an object form which key is idx and value is Math.pow(idx,2)

    • You pass in an initial empty object
    • Your method adds properties to this object
    • Method returns the object

    e.g.

     [1, 2, 3, 4, 5].reduce((o, e) => (o[e] = Math.pow(e, 2), o), {});
     // Object {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
    

    count how many letters are are in an array and turn it into the object

    • Again pass in an initial empty object
    • Method sets/adds 1 to the object based on the current letter
    • Method returns the object

    So again

    ['f', 'o', 'o', 'b', 'a', 'r'].reduce((o, e) => (o[e] = (o[e] || 0) + 1, o), {});
    // Object {f: 1, o: 2, b: 1, a: 1, r: 1}
    

    Please note the arrow notation functions I've used exploit the comma operator to return what I want, more traditionally you might write the function as e.g. followed by evolution to my examples

    function (o, e) {
        o[e] = Math.pow(e, 2);
        return o;
    }
    // same as
    function (o, e) {
        return o[e] = Math.pow(e, 2), o;
    }
    // similar to
    (o, e) => {
        return o[e] = Math.pow(e, 2), o;
    }
    // same as
    (o, e) => (o[e] = Math.pow(e, 2), o);
    
    0 讨论(0)
  • 2021-01-22 02:03

    Imagine we have the following code snippet somewhere in our application:

    function addLog() {
      console.log(arguments)
      return arguments[0] + arguments[1]
    }
    
    console.log([2,3,4].reduce(addLog))
    console.log([2,3,4].reduce(addLog, 1))
    

    Unfortunately we have a dependency on a library called badlibrary.js which will overwrite ES5's default Array.prototype.reduce:

    badlibrary.js:

    Array.prototype.reduce = Infinity
    

    Since this library is a dependency for our application, we cannot remove the library. The only solution is to fix Array.prototype.reduce by rewriting it before we run our code.

    It turns out that this is not so difficult. We can just read Mozilla's documentation on reduce and translate the English to JavaScript.

    Array.prototype.reduce = function(callback, initialValue) {
      var resultSoFar, i
      var n = this.length
      if (typeof initialValue !== 'undefined') {
        resultSoFar = initialValue
        i = 0
      } else {
        resultSoFar = this[0]
        i = 1
      }
      for (; i < n; i++) {
        resultSoFar = callback(resultSoFar, this[i], i, this)
      }
      return resultSoFar
    }
    

    Our code now works, even with this custom version of reduce, and now reduce is no longer a "black box". We could easily write it ourselves if we wanted to, and in fact, that is what several people did before ES5 was standardized. By the way, some people still use browsers that only support up to ES3. For reduce to be truly cross-browser compatible, we still need to shim it or use a utility library like Underscore/Lodash/Ramda. Using a utility library is IMO, the best and easiest solution.

    ALSO :) we have an array with lettters. some repeats some don't. I want to count how many letters are are in an array and turn it into the object form. {a:5, .... z:7}; Someone please walk me through with it. I understand forEach and map just fine, but with the reduce method, I am having very difficult time getting my head around it.

    The thing we want to return is a JS object with the letters as the keys and their counts as the values. We called this value resultSoFar in our reduce function and we are going to build that value up by calling our function on each of the elements of the array. Our initial value should be an empty object. In our function, we'll take the current letter and try to add 1 to its count. If this produces NaN (which will happen if the count is undefined i.e. when we are seeing a letter for the first time and no count has been assigned yet), then we should assign the value to 1 instead since its a new letter to count and we're seeing one of them.

    With this theory in mind, the counting code can be written as follows:

    var letters = ['a', 'b', 'c', 'a', 'b', 'a']
    console.log(letters.reduce(function(counts, currentLetter) {
        var currentLetterCount = counts[currentLetter]
        counts[currentLetter] = currentLetterCount + 1 || 1
        return counts
      }, {}))
    
    0 讨论(0)
  • 2021-01-22 02:06

    The reduce() method is an iterator it loops through all the elements in an array and does something with the results. The reduce() function accepts a callback function. This the function that actually executes whatever you want it to do for every iteration. This function is a special function

    the first parameter this function takes is previous value the second parameter this function takes is current value and two other parameters (let just make this simple)

    lets consider we have an array

    arr=[1,2,3,4,5,6]
    

    using reduce by creating a function called sum

    function sum(previousvalue,currentvalue,index,ar){
    return previousvalue+currentvalue
    }
    

    and finally we place a reference of this function in the reduce method

    arr.reduce(sum)
    

    executing this we get 21

    What really is this special function doing? let's consider

    [1,2,3,4,5,6]

    function sum says

    Wrong! "let me take the current element value in this array " == 1
    
    
    Right! # the function starts at the second element in the array so the previous element is the 1st element
    
     "let me add the current element value to the prev. element value in this array and remember this value " == 1+2
    
    
    "okay I am moving on to the next value"==3
    
    "okay..I will add the next value to the previous summed up value"==3+3
    "now I will save this value and do the same thing again until I loop to the end"
    

    But wait what is the practical use of this, I can write this easily without using the reduce function?

    It is like a generator function (like in some languages such as python)..it doesn't remember values except the previous call value and the current value...(some memory efficiency advantage)

    example finding moving averages

       function sum(previousvalue,currentvalue,index,ar){
        return (previousvalue+currentvalue/2)
        }
    

    the function above is the revision of a the same old funciton i was using

    -It takes the first two element find the average and save the value -It takes the next element add it the average and find another average and the cycle goes on

    0 讨论(0)
提交回复
热议问题