Reputation: 225
I'm beginning working with reduce and I'm having a hard time conceptualizing how to use it. I understand it when using numbers, but when it comes to objects and other data, I have a hard time following the logic. I want to take an array of objects and return an object with the keys of countryName and the value being an object with the rest of the country data. Any help would be greatly appreciated!
Data
var countries = [
{
"countryCode": "AF",
"countryName": "Afghanistan",
"population": "29121286",
"capital": "Kabul",
"continentName": "Asia"
},
{
"countryCode": "AL",
"countryName": "Albania",
"population": "2986952",
"capital": "Tirana",
"continentName": "Europe"
},
{
"countryCode": "DZ",
"countryName": "Algeria",
"population": "34586184",
"capital": "Algiers",
"continentName": "Africa"
},
]
Expected Output
{
Afghanistan: {
"countryCode": "AF",
"population": "29121286",
"capital": "Kabul",
"continentName": "Asia"
},
Albania: {
"countryCode": "AL",
"population": "2986952",
"capital": "Tirana",
"continentName": "Europe"
},
Algeria: {
"countryCode": "DZ",
"population": "34586184",
"capital": "Algiers",
"continentName": "Africa"
},
}
Base Attempt
function organizeByCountry(countries) {
return countries.reduce((acc, country) => {
return country.countryName
}, {})
}
Upvotes: 3
Views: 16121
Reputation: 31
let countries = [
{
"countryCode": "AF",
"countryName": "Afghanistan",
"population": "29121286",
"capital": "Kabul",
"continentName": "Asia"
},
{
"countryCode": "AL",
"countryName": "Albania",
"population": "2986952",
"capital": "Tirana",
"continentName": "Europe"
},
{
"countryCode": "DZ",
"countryName": "Algeria",
"population": "34586184",
"capital": "Algiers",
"continentName": "Africa"
},]
const countryName = countries.reduce((acc, country)=>{
return {...acc, [country.countryName]:country}
},{})
console.log(countryName)
Upvotes: 3
Reputation: 1606
Array.prototype.reduce in its typical usage can be visualized as a function that progressively builds your output one list entry at a time, starting with the first list entry and the accumulator you provide as the second argument (In this case, {}
).
reduce
invokes your callback for every list item (Except when you don't pass an accumulator, you can read more on this on MDN). In the first invocation in your case, the callback receives arguments as below:
acc = {};
country = {
countryCode: "AF",
countryName: "Afghanistan",
population: "29121286",
capital: "Kabul",
continentName: "Asia"
};
We now start building the result. We want an object which has keys as the country names and values as the rest of the attributes in the object. We build exactly that, by modifying the accumulator:
acc[country.countryName] = {
countryCode: country.countryCode,
population: country.population,
capital: country.capital,
continentName: country.continentName
};
We then return this modified accumulator from the callback. In the next invocation of the callback by reduce
, the callback receives this previously returned accumulator as the acc
argument and the second list item as country
:
acc = {
Afghanistan: {
countryCode: "AF",
population: "29121286",
capital: "Kabul",
continentName: "Asia"
}
};
country = {
countryCode: "AL",
countryName: "Albania",
population: "2986952",
capital: "Tirana",
continentName: "Europe"
};
At this point, we repeat and return the modified accumulator. After reduce
invokes the callback for the last time with the updated accumulator and the last item from the list, the value returned by the callback is returned by the reduce
function itself. We thus have our output now, using reduce
.
The above logic can be concisely implemented as below, while additionally avoiding mutations:
function organizeByCountry(countries) {
return countries.reduce((acc, country) => {
const {countryName, ...rest} = country;
return {...acc, [countryName]: rest};
}, {});
};
Upvotes: 10
Reputation: 191946
You can use Array.map()
to create an array of [country, object] pairs, and convert it to an object using Object.fromEntries()
:
const keyByWithoutKey = (arr, key) => Object.fromEntries(
arr.map(({ [key]: prop, ...o }) => [prop, o])
)
const countries = [{"countryCode":"AF","countryName":"Afghanistan","population":"29121286","capital":"Kabul","continentName":"Asia"},{"countryCode":"AL","countryName":"Albania","population":"2986952","capital":"Tirana","continentName":"Europe"},{"countryCode":"DZ","countryName":"Algeria","population":"34586184","capital":"Algiers","continentName":"Africa"}]
const result = keyByWithoutKey(countries, 'countryName')
console.log(result)
Upvotes: 2