1

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

3 Answers 3

3

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']))

Sign up to request clarification or add additional context in comments.

1 Comment

The if condition is not unnecessary. Code will work even without it. tally[key] = tally[key] ? tally[key] + 1 : 1 can be written as tally[key] = (tally[key] || 0) + 1
1

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([])); // {}

Comments

0

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']))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.