Javascript counting duplicates in an array
Please consider this JS function
I saw this similar question but could not figure it out.
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)
It works fine and gives the bill. I need to understand how this counts, especially (counts[ResultArray[p]] + 1) || 1;
. what does +1
and ||
.
source to share
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 "true" (something other than "false" values false
, 0
, ''
, null
, undefined
, and NaN
), otherwise it returns what is right.
If ResultArray[p]
it is not inside counts
, then it counts[ResultArray[p]]
will be undefined
. Since the undefined + 1
NaN
left side ||
is "false", so it will return the right side 1
.
Otherwise it counts[ResultArray[p]]
will be the number of times we have already seen ResultArray[p]
and add to it 1
. In this case, the left side will be "true" and will return a new bill.
source to share
The array value has not been set yet, so you cannot increment undefined. On first accessing a value, the "|| 1" part sets the initial value to 1. If it hits the same index again (which is no longer undefined and is now set to 1), it does the left side instead and increments the pre-existing value by 1.
source to share
there are a few things to keep in mind in the above algorithm:
- javascript objects are represented by sets, a dictionary is therefore
counts = {}
just a set or a dict, socounts."a"
eithercounts.a
orcounts[a]
can be used to access a value within an objectcounts
, socounts.a = 1
eithercounts["a"] = null
is an assignment to an account of set (object). - javascript dynamically allocates variables, so
counts[ResultArray[p]] since
countsis a object javascript dynamically creates the value of
ResultArray [p]]as a property or key to
counts `as javascript is loosely typed - the evaluations start from left to right on the line
counts[ResultArray[p]] = (counts[ResultArray[p]] + 1) || 1;
javascript starts evaluating starting fromcount[ResultArray[p]]
where thecounts
object (set, dictionary) evaluates, then it moves toResultArray
which evaluates the array at runtimep
then evaluates to a number that says 0 in the first iteration, so the whole evaluationcounts[ResultArray[0]]
is where javascript creates the keycounts.a
orcounts."a"
and assigns it an undefined value, then continues(counts[ResultArray[p]] + 1)
|| 1; and inside itcounts[ResultArray[p]]
, since it was already executed in the previous step, which evaluates tocounts.a
orcounts."a"
= undefined, then jumps toundefined +
, it should look like just after the left evaluation(undefined + 1)
Then javascript evaluates this inNaN
the next evaluation step
'(NaN)|| 1 where
NaNis always false but 1 is always true in javascript and true = 1 false = 0 hence 1 is assigned to
counts.aor
counts. "A" orcounts[a]
= 1
here are the steps of javascript evaluation from left to right
counts[ResultArray[p]] = (counts[ResultArray[p]] + 1) || 1;
-
counts = {}
(object, set or dict) in javascript -
ResultArray
(array) -
p
(integer) -
ResultArray[p] = "a"
in the first iteration -
counts["a"]
(undefined is assigned because there was no assignment before) - = (assignment operator)
-
counts = {}
(object, set or dict) in javascript -
ResultArray
(array) -
p
(integer) -
ResultArray[p] = "a"
in the first iteration -
counts["a"]
(undefined) -
+
(add operation) -
1
(integer) -
counts["a"] + 1 = undefined + 1 = NaN
-
NaN || 1
= 1 (boolean 1 = true false = 0 Nan = 0 = false 0 || 1 1 or operator wins) - counts ["a"] = 0 || 1 (1 is assigned to account ["a"])
source to share