Reputation: 31
I have been tasked with a counting challenge which I should return an object containing a count of elements in the array. for e.g.
expect(createTally(['a', 'b', 'a'])).to.eql({ a: 2, b: 1 });
So I have managed to do this with the higher-order function reduce but I want to be able to do this with a for loop so I can really see how this works, my code for the reduce method is below...
const createTally = items => {
const counter = items.reduce((acc, curr) => {
acc[curr] = (acc[curr] || 0) + 1
return acc
}, {})
return counter
}
So far for my for loop I have ...
const createTally = items => {
const tally = {};
let count = 0
if (items.length > 0) {
for (let i = 0; i < items.length; i++) {
if (items[i].length > count) {
count += count + 1
console.log(count)
}
const key = items[i]
tally[key] = count
return tally
}
} else {
return tally;
}
}
I am struggling to increment my count and not passing any tests other than being able to return an empty object when passed an empty array and passing 1 key value pair when given a single element, any help would be much appreciated, thank you
Upvotes: 1
Views: 2375
Reputation: 4425
A much simpler solution would yield something like the following, without all those for loops:
const createTally = (items = []) => {
const tally = {}
items.forEach(key => {
tally[key] = tally[key] ? tally[key] + 1 : 1
})
return tally
}
console.log(createTally(['a', 'b', 'a']))
Upvotes: 3
Reputation: 50684
I'm not too sure why you are checking the .length
of the item in your for-loop implementation. The main thing you need to do is iterate over your array of items using a for
loop. Then check if the current item is in your tally
object. If it already is you can increment its associated counter value, if it isn't, you can initialize its associated counter value to 1.
The for
loop won't iterate if your array length is initially 0 (ie: empty), so it will your code by default will return an empty object if this is the case.
See example below (see code comments for further details):
const createTally = items => {
const tally = {}; // acts as the `acc`
for (let i = 0; i < items.length; i++) { // loop over indexes in your array
let current = items[i]; // get current item in your array (curr)
// if statement peforms this logic seen in `.reduce()`: acc[curr] = (acc[curr] || 0) + 1
if(tally[current]) // if the current item is already a key in your object then...
tally[current]++ // increment the counter for current item
else // if the current item isn't an item in your object, then...
tally[current] = 1; // initialize the counter to 1
}
return tally; // return the `tally` (modified by the for loop)
}
console.log(createTally(['a', 'b', 'a'])); // {"a": 2, "b": 1}
console.log(createTally([])); // {}
Upvotes: 1
Reputation: 36564
You have created my unnecessary loops and condition. You just need a single loop and an if condition.
Run a loop. Check if the item is already inside the object. If it is there increase it by one. Otherwise assign it to 0
and then it will be increase by 1
.
You also don't need to check the length of the array in the start. Consider if the length
is 0
the for loop will not iterate even once and tally
will be an empty object returned at end.
const createTally = items => {
const tally = {};
for (let i = 0; i < items.length; i++) {
if (!tally[items[i]]) {
tally[items[i]] = 0;
}
tally[items[i]]++;
}
return tally
}
console.log(createTally(['a', 'b', 'a']))
Upvotes: 0