How to get to differently named array-items when iterating over the whole array?

for(let item of data) {
random = item.capital[0]}`;
}
for(let item of data) {
random = item.capital[0]}`;
}
This is how I usually do it. Every array entry has same data up to certain point, like here in the screenshot. If I were to get to native name, I woudl go:
item.name.nativeNames.fra.common
item.name.nativeNames.fra.common
But "fra" part difeeres for each entry. Sometimes it is "en", or "ita" etc. When I'm iterating, if I don't specify it won't know how to get to that "common" name, and will throw error. My question is how do I do that? xD Thanks in advance! P.S. I know you don;t like screen shots but I don;t know how else to get the data. Sorry for that
No description
37 Replies
lko
lko•5mo ago
I dont get what you're trying to do, you want to get the value of name.nativeName.fra.common but you dont know the object structure?
Dovah
DovahOP•5mo ago
I'm iterating over the whole array, that is just a single entry. Every entry has different nativeName continuation. Here it is "fra", others have "en" for example. I don't know how to get data inside while it iterates over all the items since every one has different one. So
item[0].name.nativeNames.fra.common;
item[0].name.nativeNames.fra.common;
vs
item[1].name.nativeNames.en.common;
item[1].name.nativeNames.en.common;
If I don't want to hardcode 250 items of array, I need to iterate with for loop, and I don't know how to tell it to get to that "common" part since the "fra" and "en" part is different for each entry @lko
lko
lko•5mo ago
The only way that I can think of @Dovah is to do something like
const nativeNames = item[0].name.nativeNames
const key = Object.keys(nativeNames)[0]
nativeNames[key].common
const nativeNames = item[0].name.nativeNames
const key = Object.keys(nativeNames)[0]
nativeNames[key].common
But have you generated the array yourself or are you taking it from an api?
Dovah
DovahOP•5mo ago
API
lko
lko•5mo ago
what is it? there must be a way that they show you
Dovah
DovahOP•5mo ago
Oh yeah Wait I'll ink it
Dovah
DovahOP•5mo ago
@lko
Dovah
DovahOP•5mo ago
But "borders" do not exist in the array
lko
lko•5mo ago
No description
lko
lko•5mo ago
which country are you looking at
Dovah
DovahOP•5mo ago
altSpelling ? any
lko
lko•5mo ago
From what ive seen is [country code, english name, local name] https://restcountries.com/v3.1/name/germany germany does have borders
Dovah
DovahOP•5mo ago
Yeah I see. But they are still in codes, rather than full name etc. Project is just strange and seem that API or it changed I still don't know hot to get to nativeName
lko
lko•5mo ago
@Dovah this is the native name, the third one
Dovah
DovahOP•5mo ago
Oh. Will check it out soon! Thanks, will inform you how it went
glutonium
glutonium•5mo ago
ig just deconstruct? nvm won't work u still need to name the object @Dovah
const data = {
name: {
common: "common name",
nativeName: {
fra: {
common: "desired name",
official: "other stuff"
},
test: {
name: "random data"
}
}
}
}

const [key, value] = Object.entries(data.name.nativeName)[0];

console.log(key, value)
const data = {
name: {
common: "common name",
nativeName: {
fra: {
common: "desired name",
official: "other stuff"
},
test: {
name: "random data"
}
}
}
}

const [key, value] = Object.entries(data.name.nativeName)[0];

console.log(key, value)
glutonium
glutonium•5mo ago
No description
glutonium
glutonium•5mo ago
basically the key would be the property name (which can be fra, en, ita etc), and value is the object it holds oops, u already got the solution sorry
caldane
caldane•5mo ago
fetch('https://restcountries.com/v3.1/all')
.then(response => response.json())
.then(countries =>
console.log(countries.map(c => Object.entries(c.name.nativeName || {})[0])
.reduce((acc, curr) => { curr && acc.push(curr[1].official); return acc; }, [])))
fetch('https://restcountries.com/v3.1/all')
.then(response => response.json())
.then(countries =>
console.log(countries.map(c => Object.entries(c.name.nativeName || {})[0])
.reduce((acc, curr) => { curr && acc.push(curr[1].official); return acc; }, [])))
This returned all the official names. You will have to replace the console log with how you want to capture it but I tested and it works
Dovah
DovahOP•5mo ago
@glutonium @caldane Thanks guys for all the advices! Will test em out tomorrow! 🙂
big saf 🍉
big saf 🍉•5mo ago
@caldane mind explaining that?
caldane
caldane•5mo ago
Sure thing np. First I will walk you through my thought process then I will explain how I wrote it. I wanted to look at the object in question myself so I went to the url that was linked and found the all countries url. Then I wrote a fetch in the console to log all the countries.
fetch('https://restcountries.com/v3.1/all').then(response => response.json()).then(countries => console.log(countries))
fetch('https://restcountries.com/v3.1/all').then(response => response.json()).then(countries => console.log(countries))
Then I looked at the object and figured out what data we are trying to get out of it.
[
{
"name": {
"common": "Wallis and Futuna",
"official": "Territory of the Wallis and Futuna Islands",
"nativeName": {
"fra": {
"official": "Territoire des îles Wallis et Futuna",
"common": "Wallis et Futuna"
}
}
},
"tld": [
".wf"
],
"capital": [
"Mata-Utu"
],
"altSpellings": [
"WF",
"Territory of the Wallis and Futuna Islands",
"Territoire des îles Wallis et Futuna"
],
"region": "Oceania",
"subregion": "Polynesia",
"languages": {
"fra": "French"
}
},
{
"name": {
"common": "Iceland",
"official": "Iceland",
"nativeName": {
"isl": {
"official": "ĂŤsland",
"common": "ĂŤsland"
}
}
},
"tld": [
".is"
],
"capital": [
"Reykjavik"
],
"altSpellings": [
"IS",
"Island",
"Republic of Iceland",
"Lýðveldið Ísland"
],
"region": "Europe",
"subregion": "Northern Europe",
"languages": {
"isl": "Icelandic"
}
}
]
[
{
"name": {
"common": "Wallis and Futuna",
"official": "Territory of the Wallis and Futuna Islands",
"nativeName": {
"fra": {
"official": "Territoire des îles Wallis et Futuna",
"common": "Wallis et Futuna"
}
}
},
"tld": [
".wf"
],
"capital": [
"Mata-Utu"
],
"altSpellings": [
"WF",
"Territory of the Wallis and Futuna Islands",
"Territoire des îles Wallis et Futuna"
],
"region": "Oceania",
"subregion": "Polynesia",
"languages": {
"fra": "French"
}
},
{
"name": {
"common": "Iceland",
"official": "Iceland",
"nativeName": {
"isl": {
"official": "ĂŤsland",
"common": "ĂŤsland"
}
}
},
"tld": [
".is"
],
"capital": [
"Reykjavik"
],
"altSpellings": [
"IS",
"Island",
"Republic of Iceland",
"Lýðveldið Ísland"
],
"region": "Europe",
"subregion": "Northern Europe",
"languages": {
"isl": "Icelandic"
}
}
]
Knowing that we only needed part of the object I knew a map function was in order.
fetch('https://restcountries.com/v3.1/all').then(response => response.json()).then(countries => console.log(countries.map(c => c.name.nativeName )))
fetch('https://restcountries.com/v3.1/all').then(response => response.json()).then(countries => console.log(countries.map(c => c.name.nativeName )))
This got me an array of just the data the OP was interested in, and this is where the fun part comes in. Since the OP just wanted a subset of the native name I assumed they wanted the official name so I targeted that (but they may want the common name, to which they would just have to swap out the official prop for the common prop). Since it was behind an unknown property like fra, en, or some other language code we cannot get the official or common prop. Instead we need to convert it to an array with Object.entries. I realize now we do not need the keys so actually Object.values is probably better. The reduce was needed to remove the keys but we can actually skip that if we use values make the code simpler.
fetch('https://restcountries.com/v3.1/all').then(response => response.json()).then(countries => console.log(countries.map(c => { return {name: c.name.common, ...Object.values(c.name.nativeName || {})[0]}})))
fetch('https://restcountries.com/v3.1/all').then(response => response.json()).then(countries => console.log(countries.map(c => { return {name: c.name.common, ...Object.values(c.name.nativeName || {})[0]}})))
The preceding code will extract the common name plus the natives names into an array that is uniform in schema. All the js code can be copied and pasted into a chrome dev tools console for output.
caldane
caldane•5mo ago
Example of the code in dev tools
No description
caldane
caldane•5mo ago
@big saf 🍉 Please let me know if this explanation is ok, or if it needs more detail. I am not always great at giving information in a digestible way.
big saf 🍉
big saf 🍉•5mo ago
@caldane appreciate it's better to explain than just paste code, other we don't learn anything @Dovah hope you understand! I'm also having a similar problem
Dovah
DovahOP•5mo ago
Damn. I just sat down to try it out and I got a full blow lession for free. xD Thanks a lot! Will try it myself and see if I understand it! Again, rally appreciate it! really* @caldane I pasted the code but I don't know how to catch it into variable that I can use to iterate
const response = await fetch(`https://restcountries.com/v3.1/all`);
const data = await response.json();
const response = await fetch(`https://restcountries.com/v3.1/all`);
const data = await response.json();
This is how I wrote first 2 stesp, I'm lost at
.then(countries => console.log(countries.map(c => { return {name: c.name.common, ...Object.values(c.name.nativeName || {})[0]}})))
.then(countries => console.log(countries.map(c => { return {name: c.name.common, ...Object.values(c.name.nativeName || {})[0]}})))
how do I put console log part into variable? That I can use? That whole syntax confuses me. xD
Dovah
DovahOP•5mo ago
This codepen is how I create my country card from API @caldane
caldane
caldane•5mo ago
@Dovah You were super close. I wrote it in promise syntax instead of async await because it is easier to put into the console but it looks like you may have benefit from async await syntax.
let countries;

fetch('https://restcountries.com/v3.1/all')
.then(response => response.json())
.then(data =>
countries = (data.map(c => {
return {
name: c.name.common, ...Object.values(c.name.nativeName || {})[0]
}
}))
);

console.log(countries);
let countries;

fetch('https://restcountries.com/v3.1/all')
.then(response => response.json())
.then(data =>
countries = (data.map(c => {
return {
name: c.name.common, ...Object.values(c.name.nativeName || {})[0]
}
}))
);

console.log(countries);
This feels like it should work, but it won't because of timing. You see the then code happens out of sync of the main thread so you don't know when the promis will resolve. This is where async and await can make our code look more familiar. believe it or not the following code is the same code as above, just using async await paradigm instead.
const response = await fetch(`https://restcountries.com/v3.1/all`);
const data = await response.json();
const countries = data.map(c => { return {name: c.name.common, ...Object.values(c.name.nativeName || {})[0]}});
console.log(countries);
const response = await fetch(`https://restcountries.com/v3.1/all`);
const data = await response.json();
const countries = data.map(c => { return {name: c.name.common, ...Object.values(c.name.nativeName || {})[0]}});
console.log(countries);
This code will work because we are waiting on the then part of the promise to resolve. It also has the benefit of being just a readable as our synchronous code. PS @Dovah When you are updating your countryData function don't forget to also update you for loop.
for(let item of countries) {
if(item.common === countryName) {
for(let item of countries) {
if(item.common === countryName) {
Dovah
DovahOP•5mo ago
Wow thanks for another detaild explanation! My brain is fried currently so I'll go over it later or tommorrow. xD Because I won't be able to iterate over the new array with "item" right? I will need a counter?
caldane
caldane•5mo ago
No, it is more because I changed what data you care about from the var data to countries so if you iterate of data, it will still be the old values that are not in the shape you desire.
Dovah
DovahOP•5mo ago
@caldane
const currencies = data.map(c => { return {...Object.values(c.currencies || {})}});
const currencies = data.map(c => { return {...Object.values(c.currencies || {})}});
I did this for currencies Since some have more than one, and need to display them all. It seems to work, but I don't know how to iterate over them or how to even get an length of it. usual forOf does not seem to work It says it is "not iterable" @caldane OK got it. xD
Object.keys(currencies[i]).length
Object.keys(currencies[i]).length
Ol friend google gave the answer Actualy it does not work for more than 1 xD Ok done. xD Alright all is done! Thanks a lot. You were a lot of help! @caldane
caldane
caldane•5mo ago
I am so glad I was able to help
Dovah
DovahOP•5mo ago
Also, I used a roundabout way for for loop, like this
let i = data.indexOf(item);
currencies(i)
let i = data.indexOf(item);
currencies(i)
But that is all the juice left in my brain. To not bother you further, since you did more than enough! Really appreciate it! đź‘Ť
caldane
caldane•5mo ago
const response = await fetch('https://restcountries.com/v3.1/all')
const data = await response.json()
const countries = data.map(c => {
return {
name: c.name.common, //Get the global common name (not the native common name)
...Object.values(c.name.nativeName || {})[0], //Add the native common name and native official name
currencies: Object.values(c.currencies || {}) //Add the currencies as an array.
}
}).sort((a,b) => a.name.localeCompare(b.name))))
const response = await fetch('https://restcountries.com/v3.1/all')
const data = await response.json()
const countries = data.map(c => {
return {
name: c.name.common, //Get the global common name (not the native common name)
...Object.values(c.name.nativeName || {})[0], //Add the native common name and native official name
currencies: Object.values(c.currencies || {}) //Add the currencies as an array.
}
}).sort((a,b) => a.name.localeCompare(b.name))))
instead of getting your currencies that way, which is less efficient because you have to lookup your item each iteration, you could instead add it to your countries variable that you are already iterating through. This way you already will have the data in the loop.
Want results from more Discord servers?
Add your server