0

Okay I researched this one and couldn't find an answer here so hopefully this isn't a duplicate. I'm also trying not to be specific in order to figure this out on my own.

var arr = ['cat','car','cat','dog','car','dog']

function orgNums(input) {
    var count = 0;
    var obj = {};
    for (var i = 0; i < input.length; i++) {
        if (input[i] === 'cat')
        obj['cat'] = count++;
    }
    return obj;
}

I want it to return {cat:2} but I'm getting {cat:1}

Eventually I want it to return {cat:2, car:1, dog:2, gerbil:1}

So I tried using obj[cat] = ++count and I'm getting the answer I want, but when I try a second if statement: if input[i] === 'dog', obj[dog] = ++countI get {cat:2, dog:4}. I noticed that it's taking what count already is at, 0, then moves it to 2 to count cat, then moves it to 4, taking the dog count of 2 and adding 2 to it. How do I prevent that from happening so that count restarts at 0 each time?

EDIT: So this works beautifully var arr = ['cat', 'car', 'cat', 'dog', 'car', 'dog']

function orgNums(input) {
    var obj = {};

    for (var i = 0; i < input.length; i++) {
        obj[input[i]] = obj[input[i]] || 0;
        obj[input[i]]++;
    }
    return obj;
}

console.log(orgNums(arr));

but the final output i actually want is:

[
{cat:1
dog:2
}
{car:2
}
]

So I tried throwing in an if statement like this:

if (input[i] === 'cat'||'dog')

but it's still throwing car into the object. I'll try to figure out the multiple objects in the array. Thanks again!

bikedres
  • 135
  • 1
  • 10
  • it's a mapReduce algorithm problem – kevin ternet Oct 10 '16 at 16:31
  • 1
    *I researched this one and couldn't find an answer* You can't research how to **think**. Start off by writing down **in English** how you intend to solve the problem. Talk yourself through your algorithm and convince yourself it's right; try working it out on paper. Then and only then convert it into JS, possibly a little bit at a time if you can figure out how to break your problem down, and make sure it continues to work at each step. While you're doing this, you'll find the debugger extremely helpful--walk though your code, examining variables. –  Oct 10 '16 at 16:36

2 Answers2

2

You could just reduce the array, and count the keys as you go

var arr = ['cat', 'car', 'cat', 'dog', 'car', 'dog', 'horse'];

function orgNums(input) {
    return input.reduce((a, b) => {
      return b in a ? a[b]++ : a[b] = 1, a;
    }, {});
}

console.log(orgNums(arr));
adeneo
  • 312,895
  • 29
  • 395
  • 388
2

The assignment of count, which is used in the loop, does not work in this case, because of the postfix increment count++. This gives you the value of the counter and increment later, If you take the prefix increment ++count, you get the incremented value assigned.

// Postfix 
var x = 3;
y = x++; // y = 3, x = 4

// Prefix
var a = 2;
b = ++a; // a = 3, b = 3

But you can omit the variable and count directly with a property of the object. for all items in one loop.

You could use the element as key for the object. Then assign with zero, if not exist and increment.

var arr = ['cat', 'car', 'cat', 'dog', 'car', 'dog']

function orgNums(input) {
    var obj = {};

    for (var i = 0; i < input.length; i++) {
        obj[input[i]] = obj[input[i]] || 0;
        obj[input[i]]++;
    }
    return obj;
}

console.log(orgNums(arr));

A more compact version of the above with Array#forEach

var arr = ['cat', 'car', 'cat', 'dog', 'car', 'dog']

function orgNums(input) {
    var obj = {};

    input.forEach(function (item) {
        obj[item] = (obj[item] || 0) + 1;
    });
    return obj;
}

console.log(orgNums(arr));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • great! so this solved the first part of what i'm doing and i was trying to figure out the 2nd portion with minimal help but i'm struggling. eventually i want the output to look like [ { cat:2, dog:1 } {car:1} ]... i tried if(input[i] === 'cat'||'dog' , but it's still giving me {cat:2, dog:1, car:1}. any hints? – bikedres Oct 10 '16 at 17:12