Reputation: 31
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
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
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
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