user1207289
user1207289

Reputation: 3253

javascript counting duplicates in array

Please consider this JS function

I have seen this similar question but couldn't understand.

function a (ResultArray){
    var counts={};
    for ( p = 0; p < ResultArray.length; p++){            
        counts[ResultArray[p]] = (counts[ResultArray[p]] + 1) || 1;            
    }
    return counts;
}

var arr = ["a","b","c","d","a","b","e"];        
var res = new a(arr);
console.log(res)

Its working fine and giving the count. I need to understand how is it giving the count, specially (counts[ResultArray[p]] + 1) || 1; part. what is +1 and || doing.

Upvotes: 3

Views: 4365

Answers (3)

sachgits
sachgits

Reputation: 345

there are some things to keep in mind in the above algorithm

  1. javascript objects are represented by sets, dictionary hence counts = {} is just a set or dict hence counts."a" or counts.a or counts[a] can all be used to access the value inside of counts object therefore counts.a = 1 or counts["a"] = null is an assignment to counts set (object).
  2. javascript dynamically allocates variables hence counts[ResultArray[p]] sincecountsis a object javascript dynamically creates the value of ResultArray[p]]as a property or key tocounts` as javascript is loosely typed
  3. evaluations start from left to right on the line counts[ResultArray[p]] = (counts[ResultArray[p]] + 1) || 1; javascript start evaluating starting from count[ResultArray[p]] where counts evaluates to an object (set, dictionary) then it moves to ResultArray which evaluates to array during runtime p is then evaluated to a number say 0 in first iteration hence the whole evaluation is counts[ResultArray[0]] where javascript creates the key counts.a or counts."a" and assigns to it undefined evaluation then continues to (counts[ResultArray[p]] + 1) || 1; and inside of it counts[ResultArray[p]] since it had already done in previous step that evaluates to counts.a or counts."a" = undefined then moves to undefined + this should look like this after left right evaluation (undefined + 1) javascript then evaluates that to NaN in the next step of evaluation
    '(NaN)|| 1 whereNaNis always false but 1 is always true in javascript and true = 1 false = 0 hence 1 is assigned tocounts.aorcounts."a" or counts[a] = 1

here is javascript evaluation steps from left to right broken down counts[ResultArray[p]] = (counts[ResultArray[p]] + 1) || 1;

  1. counts = {} (object,set or dict) in javascript
  2. ResultArray (array)
  3. p (integer)
  4. ResultArray[p] = "a" in first iteration
  5. counts["a"] (undefined is assigned since there was no previous assignement)
  6. = (assignment operator)
  7. counts = {} (object,set or dict) in javascript
  8. ResultArray (array)
  9. p (integer)
  10. ResultArray[p] = "a" in first iteration
  11. counts["a"] (undefined)
  12. + (addition operation)
  13. 1 (integer)
  14. counts["a"] + 1 = undefined + 1 = NaN
  15. NaN || 1 = 1 (boolean 1 = true false = 0 Nan = 0 = false 0 || 1 1 wins in or statement)
  16. counts["a"] = 0 || 1 (1 is assigned to counts["a"])

Upvotes: 0

Peter Olson
Peter Olson

Reputation: 142921

I guess the main confusion comes from this line:

counts[ResultArray[p]] = (counts[ResultArray[p]] + 1) || 1;

The || operator returns what is on the left side if it is "truthy" (anything other than the "falsy" values false, 0, '', null, undefined, and NaN), otherwise it returns what is on the right hand side.

If ResultArray[p] is not inside of counts, then counts[ResultArray[p]] will be undefined. Since undefined + 1 is NaN, the left hand side of || is "falsy", so it will return the right hand side 1.

Otherwise, counts[ResultArray[p]] will be the amount of times we've already seen ResultArray[p], and we'll add 1 to it. In this case the left hand side will be "truthy" and it will return the new count.

Upvotes: 3

ebraley
ebraley

Reputation: 206

The array value hasn't been set yet, so you can't increment undefined. The first time it hits a value, the "|| 1" portion sets the initial value to 1. If it hits that same index again (which is no longer undefined and now set to 1), it executes the left side instead and increments the pre-existing value by 1.

Upvotes: 1

Related Questions