in method problems in javascript

Viewed 58

I was trying to find as a dictionary (JS object) how many times each of the elements appears in some list. For example, the appearance of 1 in the list [1,1,2,2,1,3,4] is 3, because there are three ones in the list. In python I would implement this in the following way:

l = [1,1,2,2,1,3,4]
apr = dict()

for e in l:
    if (e in apr.keys()):
        apr[e] += 1
    else:
        apr[e] = 1

In javascript I decided to do

var arr = [1,1,2,2,1,3,4];

var vals = {};

for (let e of arr){
    if (e in Object.keys(vals)){        
        vals[e] = vals[e] + 1;
    }
    else{
        
        vals[e] = 1;
    }
}

// vals = { '1': 2, '2': 1, '3': 1, '4': 1 }

which is obviously wrong. Then I tried if (Object.keys(vals).includes(e)){ instead, and it didn't work either. At the very end I implemented my own function my_in, and the progem worked:

function my_in(val,arr){
    for (i = 0; i<=arr.length; i++){
        if (val==arr[i]){
            return true;
        }
    }
    return false;
}

var arr = [1,1,2,2,1,3,4];

var vals = {};

for (let e of arr){
    //if (Object.keys(vals).includes(e)){
    // if (e in Object.keys(vals)){
    if (my_in(e, Object.keys(vals))) {
        
        vals[e] = vals[e] + 1;
    }
    else{
        
        vals[e] = 1;
    }
}

console.log(vals);

But I am still confused why did the first two tries didn't work. Is there anything I should be aware of when using in or includes()?

2 Answers

You need to use in operator with the object, not with an array this would check the indices.

For example by using an an array of keys

vals = { 1: 1 }
keys = Object(vals) // ['1']

if (1 in keys) performs 
-> 1 in { 0: 1, length: 1 }, because there is only index zero with value one
-> false

var arr = [1, 1, 2, 2, 1, 3, 4];
var vals = {};

for (let e of arr) {
    if (e in vals) {           // check with object
        vals[e] = vals[e] + 1;
    } else {
        vals[e] = 1;
    }
}

console.log(vals);

The Object.keys(object) function returns an array of the string keys in the object.

When you do if (e in Object.keys(vals)) this would actually check the e element in the array returned from the Object.keys call. Which is not what you want.

You should simply check the presence of the e key in the vals object, if present increment by 1 else assign 0 to it:

var arr = [1,1,2,2,1,3,4];

var vals = {};

for (let e of arr){
   vals[e] = (vals[e] || 0) + 1;
}
console.log(vals)

The issue with your code was, when you did Object.keys(vals) for the first iteration it returned an empty array [] as vals was an empty object {}. So e in Object.keys(vals) was false and it went to the else block. In the else block the vals[e] = 1 was executed.

In the next iteration when the check e in Object.keys(vals) happened it was evaluated to true as the array ["1"] was returned because vals is {1: 1}, same for the other elements so that is why you see {1: 2, 2: 1...}.

Related