Reputation: 2834
I am trying to create a function that creates an object and counts the number duplicates per number in an array. For example if I have an array that is [1,2,2,2,3,3]
my function should return 3 because there are two duplicates of 2
and one duplicate of 3
. So I wrote a function that I thought was clever. I decided to create a mapping of frequences of each element. By setting the creation of each new property i.e. unique number in the array equal to -1. For some reason when I do this I get property values that are all equal to zero. I am getting two different sets of results from the two functions below.
function DistinctListV1(arr) {
var mapping = {};
for(var i = 0; i < arr.length; i++){
if(!mapping[arr[i]]){
mapping[arr[i]] = 0; //Difference here
}
mapping[arr[i]] += 1;
}
return mapping
}
function DistinctListV2(arr) {
var mapping = {};
for(var i = 0; i < arr.length; i++){
if(!mapping[arr[i]]){
mapping[arr[i]] = -1; //Difference here
}
mapping[arr[i]] += 1;
}
return mapping
}
DistinctListV1([1,2,2,3,3,3])
=> { '1': 1, '2': 2, '3': 3 }
DistinctListV2([1,2,2,3,3,3])
=> { '1': 0, '2': 0, '3': 0 }
Right now I am only concerned about creating an object with this mapping. Thanks for reading.
Edit:
=> DistinctListV3([1,2,2,3,3,3])
function DistinctListV3(arr) {
var mapping = {};
for(var i = 0; i < arr.length; i++){
if(!mapping[arr[i]]){
mapping[arr[i]] = 100; //Difference here
}
mapping[arr[i]] += 1;
}
return mapping
}
DistinctListV3([1,2,2,3,3,3])
=> { '1': 101, '2': 102, '3': 103 }
Using this example, leads me to believe something is going on when I use -1 as the place to start incrementing.
Upvotes: 0
Views: 50
Reputation: 7315
The problem you're running into is caused by this line:
if(!mapping[arr[i]]){
I think you're expecting the code inside that if
to only run when mapping[arr[i]]
doesn't exist yet. But the !
operator isn't strict: it will return true
not just when mapping[arr[i]]
is undefined
, but also when mapping[arr[i]]
is anything falsy, such as the number zero. This, of course, happens when you initialise the variable to -1
and then add 1
to it, causing all your mappings to be stuck at 0
indefinitely (they keep being set to -1
then incremented, meaning they are back to 0
and the if
runs again and again, never getting above 0
).
You want a more strict check:
if (typeof mapping[arr[i]] === 'undefined') {
Or
if (mapping.hasOwnProperty(arr[i])) {
Upvotes: 2
Reputation: 2164
!mapping[arr[i]]
is true
for undefined
AND 0
, which is why your first works and your second doesn't. The first time you add 1 to a property on mapping
in DistinctListV2
it becomes 0, then the next time it finds the same number, !mapping[arr[i]]
is true
, so it sets that property to -1 again.
The fix is simple:
function DistinctListV2(arr) {
var mapping = {};
for(var i = 0; i < arr.length; i++){
if(mapping[arr[i]] === undefined){ // Check for undefined, not 'falsey'
mapping[arr[i]] = -1;
}
mapping[arr[i]] += 1;
}
return mapping
}
Upvotes: 0
Reputation: 1618
What if you just dynamically create the object?
Something like:
var counterObject = {};
var duplicateCounter = 0;
for (var i = 0; i < array.length; i ++ ){
var item = array[i];
if (!counterObject[item]) {
counterObject[item] = 'placeholder';
} else {
duplicateCounter++
}
}
I did not test it, but the flow is: loop through array, grab item at i. Item at i is checked against the object. If it is there, then it must be a duplicate, so we increment the duplicate counter. If not, we assign some arbitrary value with the item name as the key, so that when we encounter it again we can increment. If you wanted to also see how many of each, you can set the 'placeholder' to 0, and then in the else {} increment hte count of that value in the object.
Upvotes: 0