简体   繁体   中英

Counting instances of values in an object (initial value for array.reduce)

I have the following code to count number of each word in given string:

function countWords(str) {
  if (str === "") {
    return {};
  }
  var holder = str.split(" ");
  var holder1 = holder.reduce(function (allNames, name) {
    if (name in allNames) {
      allNames[name]++;
    }
    else {
      allNames[name] = 1;
    }
    return allNames;
  }, {});
  return holder1;
}

countWords("Here I I am here here");

I understand everything that is going on in the code, but I can't understand why none of my tests passes unless I have the empty object {} located on line 18 after the comma. Can someone please explain the purpose of this? Thanks in advance.

Its because how reduce is defined, according to documentation :

array.reduce(callback, [initialValue])

where callback is callback Function to execute on each value in the array, taking four arguments:

accumulator: The accumulated value previously returned in the last invocation of the callback, or initialValue, if supplied.

currentValue: The current element being processed in the array.

currentIndex: The index of the current element being processed in the array. Starts at index 0, if an initialValue is provided, and at index 1 otherwise.

array: The array reduce was called upon.

but the important tip here is this:

The first time the callback is called, accumulator and currentValue can be one of two values. If initialValue is provided in the call to reduce, then accumulator will be equal to initialValue and currentValue will be equal to the first value in the array.

If no initialValue was provided, then accumulator will be equal to the first value in the array and currentValue will be equal to the second.

in your code, the holder var is:

holder = ["Here", "I", "I", "am", "here", "here"]

when we specify the initialValue as an empty object {} (as set in line 18), we have this at first iterate:

allNames = {}, name = "Here"

which is ok to start as allNames is an array and we can use allNames[name] properly to count number of repeats for each word.

But if we omit the initial value, then in first iterate, we will have:

allNames = "Here", name = "I"

which is completely wrong in our scenario.

  • The syntax for reduce method is arr.reduce(callback, [initialValue]);

  • The callback function can take 4 arguments which are accumulator, currentValue, currentIndex and array

  • You are using just two parameters in your function which is fine.

    accumulator - is for holding whatever value you returned from the last invocation of callback currentValue - is for holding the current value which is being processed

  • If you had not used initialValue then , for the first iteration, accumulator will hold the first value in the array which in your case would have been the string "Here" .

 var sum = ["a"].reduce(function(acc, val) { return acc; }); console.log(sum); 

  • If you use the initialValue and set to an object literal {} , then for the first iteration, accumulator will hold the value initialValue .

 var sum = ["a"].reduce(function(acc, val) { return acc; }, 5); console.log(sum); 

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