【问题标题】:How to reduce array of objects into one object?如何将对象数组减少为一个对象?
【发布时间】:2021-09-02 03:35:15
【问题描述】:

我开始使用 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 
  }, {})
}

【问题讨论】:

    标签: javascript arrays object reduce


    【解决方案1】:

    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 函数本身返回。因此,我们现在有了输出,使用 reduce


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

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

    【讨论】:

    • 感谢您的深入解释!这对我有很大帮助。您的重构解决方案仍然让我感到困惑,但我会掌握它的!
    • 很高兴为您提供帮助!查看这些MDN 文档中的对象解构部分,我相信它们会很有用。
    【解决方案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)

    【讨论】:

      【解决方案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)

      【讨论】:

        猜你喜欢
        • 2022-01-22
        • 1970-01-01
        • 2017-08-17
        • 2021-09-16
        • 1970-01-01
        • 2021-04-02
        • 2018-07-18
        • 2019-09-30
        • 2018-01-05
        相关资源
        最近更新 更多