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

How to reduce array of objects into one object?

我开始使用 reduce,但我很难概念化如何使用它。使用数字时我理解它,但是当涉及到对象和其他数据时,我很难遵循逻辑。我想获取一个对象数组和 return 一个对象,其键为 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 
  }, {})
}

您可以使用 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)

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
};

然后我们 return 从回调中修改累加器。在 reduce 对回调的下一次调用中,回调接收这个先前 returned 的累加器作为 acc 参数,第二个列表项作为 country:

acc = {
  Afghanistan: {
    countryCode: "AF",
    population: "29121286",
    capital: "Kabul",
    continentName: "Asia"
  }
};
country = {
  countryCode: "AL",
  countryName: "Albania",
  population: "2986952",
  capital: "Tirana",
  continentName: "Europe"
};

此时,我们重复 return 修改后的累加器。在 reduce 最后一次使用更新的累加器和列表中的最后一项调用回调后,回调 return 的值由 reduce 编辑 return本身发挥作用。因此,我们现在有了输出,使用 reduce.


以上逻辑可以简明地实现如下,同时还避免了突变:

function organizeByCountry(countries) {
  return countries.reduce((acc, country) => {
    const {countryName, ...rest} = country;

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

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)