如何将对象数组缩减为一个对象?

3

我开始学习使用 reduce,但是在如何使用它的概念上遇到了困难。当使用数字时我理解它的作用,但当涉及到对象和其他数据时,我很难跟进逻辑。我想要取一个对象数组并返回一个具有 countryName 键和值为其余国家数据的对象。任何帮助将不胜感激!

数据

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"
  },
]

预期输出

{
  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"
  },
}

基础尝试

function organizeByCountry(countries) {
  return countries.reduce((acc, country) => {

    return country.countryName 
  }, {})
}
3个回答

10

Array.prototype.reduce 的典型用法可以被视为一种函数,它逐渐地构建输出,每次一个列表项,从第一个列表项和由您提供的第二个参数作为累加器开始 (在这种情况下,{}

reduce 会为每个列表项调用您的回调函数 (除非您没有传递累加器,在这种情况下您可以在MDN上阅读更多信息)。在您的情况下,第一次调用中,回调函数接收以下参数:

acc = {};
country = {
  countryCode: "AF",
  countryName: "Afghanistan",
  population: "29121286",
  capital: "Kabul",
  continentName: "Asia"
};

现在我们开始构建结果。我们需要一个对象,其键是国家名称,值是对象中其余属性。通过修改累加器,我们正好构建这样的对象:
acc[country.countryName] = {
  countryCode: country.countryCode,
  population: country.population,
  capital: country.capital,
  continentName: country.continentName
};

我们将修改后的累加器从回调函数中返回。在下一次reduce调用回调函数时,回调函数将以先前返回的累加器作为acc参数,并以第二个列表项作为country参数。
acc = {
  Afghanistan: {
    countryCode: "AF",
    population: "29121286",
    capital: "Kabul",
    continentName: "Asia"
  }
};
country = {
  countryCode: "AL",
  countryName: "Albania",
  population: "2986952",
  capital: "Tirana",
  continentName: "Europe"
};

在这一点上,我们重复并返回修改后的累加器。在最后一次使用更新后的累加器和列表中的最后一个项目调用回调后,回调返回的值将由reduce函数本身返回。因此,我们现在使用reduce获得了输出。
上述逻辑可以如下简洁地实现,同时避免突变:
function organizeByCountry(countries) {
  return countries.reduce((acc, country) => {
    const {countryName, ...rest} = country;

    return {...acc, [countryName]: rest};
  }, {});
};

非常感谢您的深入解释!这对我帮助很大。您重构后的解决方案仍然让我感到困惑,但我会逐渐理解的! - mfaccord
很高兴能帮忙!请查看这些MDN文档中的对象解构部分,我相信它们会很有用。 - hexbioc

3

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)


2
您可以使用Array.map()创建一个[country, object]对的数组,并使用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)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接