How do I count the occurrences of a string within multiple arrays that are part of an object?

136 views Asked by At

I have an exercise that requires me to use a for loop to iterate through the object 'tutorPetTypes' and calculate the collective total number of cats owned by the tutors.

Here's my current code. It runs but results in totalCats = 0, whereas It should be 7.

If I console.log(tutor) as part of the if statement, I can see that it's correctly iterating through the tutors but I'm obviously missing something in terms of correctly checking the array for "cat".

const tutorPetTypes = {
  'Sarah': ['cat'],
  'Jim': ['dog', 'dog'],
  'Joe': ['mouse'],
  'Róisín': ['cat','cat','cat','cat','cat','dog'],
  'Edd': ['lizard', 'cat'],
  'Lewis': ['bearded dragon', 'tortoise']
}

let totalCats = 0

//Solution to be provided below

for (const tutor in tutorPetTypes) {
  for (let i = 0; i < tutor.length; i++) {
      if (tutor[i] === "cat") {
      totalCats++;
    };
  };
};

Any help would be greatly appreciated.

2

There are 2 answers

0
Zac On

Thank you everyone for your responses.

I find it interesting how no one was willing to provide a solution using for... in, and I don't mean that in a critical way, just observational. As clearly there are more advanced functions that provide a more suitable solution to this exercise given that so many people suggested it i.e. Object.values. However, the exercise specifically required that I use the a for... in loop. (I don't know why) And your responses did help me in analysing my solution and eventually coming up with a working one. Which is this:

for (const tutor in tutorPetTypes) {
  for (let i = 0; i < tutor.length; i++) {
      if (tutorPetTypes[tutor][i] === "cat") {
      totalCats++;
    };
  };
};

It simply needed [tutor][i] changing to tutorPetTypes[tutor][i]

Previously it was iterating through each letter of the tutors name, hence === 'cat' returned 0.

0
Timur On

You should consider using the for...of loop on the values of the object instead. Example below.

I also included an alternative in case you are allowed to get away from the for loop. In that alternative, you could map the object's values and filter the animals array of each person to return only the cats. Then, flatten the array, since the map result will be a nested array of arrays, and get it's length.

const tutorPetTypes = {
  Sarah: ['cat'],
  Jim: ['dog', 'dog'],
  Joe: ['mouse'],
  Róisín: ['cat', 'cat', 'cat', 'cat', 'cat', 'dog'],
  Edd: ['lizard', 'cat'],
  Lewis: ['bearded dragon', 'tortoise'],
}

let totalCats = 0

for (const animals of Object.values(tutorPetTypes)) {
  for (let i = 0; i < animals.length; i++) {
    if (animals[i] === 'cat') {
      totalCats++
    }
  }
}

console.log(totalCats)

// To be consistent with for...of, you can do:
totalCats = 0
for (const animals of Object.values(tutorPetTypes)) {
  for (const type of animals) {
    if (type === 'cat') {
      totalCats++
    }
  }
}

console.log(totalCats)

// Another alternative would be:
totalCats = Object.values(tutorPetTypes)
  .map((animals) => animals.filter((type) => type === 'cat'))
  .flat().length

console.log(totalCats)