Terry
Terry

Reputation: 31

Accessing objects

I wrote a simple function to access some values in the array below, and nested in the array are multiple objects.

My question has to do with my 2 loops. I understand that I must initially loop through the array to gain access to the 3 objects, but why must I loop through the 3 objects before I can access the values?

Basically why can't I run an initial for loop and access a sound by doing this:

animalNoises[i][animal][country]

the above returns as undefined for me. Does it have something to do with the way each 3 animal objects are structured?

Thanks for the help. I really appreciate the stack overflow community for the constant help.

function petSounds(animal, country) {
let phrase = ''
for (let i = 0; i < animalNoises.length; i++) {
  for (let key in animalNoises[i]){
    if (animal === key){
      let sound = animalNoises[i][key][country];
      phrase = animal + 's' + ' in ' + country + ' say ' + sound
      }
    }
  }
 return phrase
}

    let animalNoises = [
  { 'dog': {
    'America' : 'Woof! Woof!',
    'Germany' : 'Wau Wau!',
    'England' : 'Bow wow!',
    'Uruguay' : 'Jua jua!',
    'Afrikaans' : 'Blaf!',
    'Korea' : 'Mong mong!',
    'Iceland' : 'Voff voff!',
    'Albania' : 'Ham!',
    'Algeria' : 'Ouaf ouaf!'
    }
  },
  { 'cat': {
    'America' : 'Meow',
    'Germany' : 'Miauw!',
    'England' : 'mew mew',
    'Uruguay' : 'Miau Miau!',
    'Afrikaans' : 'Purr',
    'Korea' : 'Nyaong!',
    'Iceland' : 'Kurnau!',
    'Albania' : 'Miau',
    'Algeria' : 'Miaou!'
    }
  },
  { 'chicken': {
    'America' : 'Cluck cluck',
    'Germany' : 'tock tock tock',
    'England' : 'Cluck Cluck',
    'Uruguay' : 'gut gut gdak',
    'Afrikaans' : 'kukeleku',
    'Korea' : 'ko-ko-ko',
    'Iceland' : 'Chuck-chuck!',
    'Albania' : 'Kotkot',
    'Algeria' : 'Cotcotcodet'
    }
  }
];

Upvotes: 2

Views: 125

Answers (3)

Robert Mennell
Robert Mennell

Reputation: 2052

If you want to keep the form you have now you can always use an Array#find(), and then a in operator check, and then with template literals you can easily create your string.

function petSounds(animal, country) {
 const noise = animalNoises.find(obj => animal in obj)[animal][country];
 return `${animal}s in ${country} say ${noise}`
}

    let animalNoises = [
  { 'dog': {
    'America' : 'Woof! Woof!',
    'Germany' : 'Wau Wau!',
    'England' : 'Bow wow!',
    'Uruguay' : 'Jua jua!',
    'Afrikaans' : 'Blaf!',
    'Korea' : 'Mong mong!',
    'Iceland' : 'Voff voff!',
    'Albania' : 'Ham!',
    'Algeria' : 'Ouaf ouaf!'
    }
  },
  { 'cat': {
    'America' : 'Meow',
    'Germany' : 'Miauw!',
    'England' : 'mew mew',
    'Uruguay' : 'Miau Miau!',
    'Afrikaans' : 'Purr',
    'Korea' : 'Nyaong!',
    'Iceland' : 'Kurnau!',
    'Albania' : 'Miau',
    'Algeria' : 'Miaou!'
    }
  },
  { 'chicken': {
    'America' : 'Cluck cluck',
    'Germany' : 'tock tock tock',
    'England' : 'Cluck Cluck',
    'Uruguay' : 'gut gut gdak',
    'Afrikaans' : 'kukeleku',
    'Korea' : 'ko-ko-ko',
    'Iceland' : 'Chuck-chuck!',
    'Albania' : 'Kotkot',
    'Algeria' : 'Cotcotcodet'
    }
  }
];

Otherwise with your version you're looping while looping when you can just simply check for existence.

Of course there are many ways to skin a cat, so the above is equivalent to

function petSounds(animal, country) {
 const noise = animalNoises.find(obj => obj.hasOwnProperty(animal))[animal][country];
 return `${animal}s in ${country} say ${noise}`
}

Of course if you are receiving this JSON from somewhere else you could do a reduction on it and then associate the keys and values into a super object(using Array#reduce() and Object.entries())

animalNoises = animalNoise.reduce((acc, obj) => {
  Object.entries(obj).forEach(([key, value]) => {
   acc[key] = value;
  });
  return acc;
 },
 {}
)

function petSounds(animal, country) {
  return `${animal}s in ${country} say ${animalNoises[animal][country]}`;
}

If you want to learn more about the cool things you can do with Arrays you should check out the MDN for JavaScript Arrays

The in operator is a really useful way to make Object#hasOwnProperty() shorter

And as always a lot more information about JavaScript can be found at the MDN


Some extra fun with Object Sestructuring for just another way to arrange things:

function petSounds(animal, country) {
 const { [animal]: { [country]: noise } } = animalNoises.find(obj => animal in obj);
 return `${animal}s in ${country} say ${noise}`
}

Upvotes: 1

Gautam
Gautam

Reputation: 58

Your solution works, with single for loop. You missed specifying single quotes. When I simply console this it returns specific value.

animalNoises[0]['dog']['Korea']
"Mong mong!"

In loop you need to access from your array by specifying key name and country values.

It doesn't have anything to do with the way each 3 animal objects are structured

When I call your function it is running fine.

petSounds('dog', 'Korea')
"dogs in Korea say Mong mong!"

Or you can modify your function as below which does same reducing inner loop:

function petSounds(animal, country) {
let phrase = ''
  for (let i = 0; i < animalNoises.length; i++) {
    let key = Object.keys(animalNoises[i])[0];
    if (animal === key){
      let sound = animalNoises[i][key][country];
      phrase = animal + 's' + ' in ' + country + ' say ' + sound
    }
  }
  return phrase
}

Upvotes: 1

Jatin Kathrotiya
Jatin Kathrotiya

Reputation: 539

You need to update your json to simplify function (use an object keyed by animal type):

function petSounds(animal, country) {
  const sound = animalNoises[animal][country];
  const phrase = animal + 's' + ' in ' + country + ' say ' + sound;
  return phrase;
}

let animalNoises = {
  'dog': {
    'America': 'Woof! Woof!',
    'Germany': 'Wau Wau!',
    'England': 'Bow wow!',
    'Uruguay': 'Jua jua!',
    'Afrikaans': 'Blaf!',
    'Korea': 'Mong mong!',
    'Iceland': 'Voff voff!',
    'Albania': 'Ham!',
    'Algeria': 'Ouaf ouaf!'

  },
  'cat': {
    'America': 'Meow',
    'Germany': 'Miauw!',
    'England': 'mew mew',
    'Uruguay': 'Miau Miau!',
    'Afrikaans': 'Purr',
    'Korea': 'Nyaong!',
    'Iceland': 'Kurnau!',
    'Albania': 'Miau',
    'Algeria': 'Miaou!'
  },
  'chicken': {
    'America': 'Cluck cluck',
    'Germany': 'tock tock tock',
    'England': 'Cluck Cluck',
    'Uruguay': 'gut gut gdak',
    'Afrikaans': 'kukeleku',
    'Korea': 'ko-ko-ko',
    'Iceland': 'Chuck-chuck!',
    'Albania': 'Kotkot',
    'Algeria': 'Cotcotcodet'
  }
};

console.log(petSounds('cat', 'America'));
console.log(petSounds('dog', 'Iceland'));
console.log(petSounds('chicken', 'Germany'));

Upvotes: 4

Related Questions