【问题标题】:How to merge two array of object如何合并两个对象数组
【发布时间】:2022-01-04 16:29:05
【问题描述】:

array1 = [
{
    "name": 
    {
        "common": "Afghanistan",
        "official": "Islamic Republic of Afghanistan",
        "capital": [ "Kabul" ]
    }
}]
array2 = [
{
    "capital": [ "Kabul" ],
    "population": 2837743
}];

我想做

[{
    "name": 
    {
        "common": "Afghanistan",
        "official": "Islamic Republic of Afghanistan",
        "capital": [ "Kabul" ],
        "population": 2837743
    }
}]

我想合并到一个对象数组并创建一个数组。我尝试使用过滤方法和查找方法来解决问题,但无法解决问题

【问题讨论】:

  • 请注意,您可能不想将capital 作为数组,一个国家应该只有一个首都。
  • "...尝试使用 filter 方法和 find 方法..." - 那个方法在哪里?
  • 这能回答你的问题吗? Merge 2 arrays of objects
  • 是的,这里两个array-like 两个表中的主键是大写,如何合并得到一个表,同一个国家应该只有一个大写
  • array2 不是数组

标签: javascript arrays ecmascript-6 merge


【解决方案1】:

首先处理array2的数据,构建任意一个key为capitol,value为object的对象。使用map 和array1 并从流程数据(track2)中添加相应的首都信息

const array1 = [
  {
    name: {
      common: "Afghanistan",
      official: "Islamic Republic of Afghanistan",
    },
    capital: ["Kabul"],
  },
];

const array2 = [
  {
    capital: ["Kabul"],
    population: 2837743,
  },
];

const track2 = {};
array2.forEach(({ capital: [city], ...rest }) => (track2[city] = rest));

const result = array1.map((item) => ({
  ...item,
  ...track2[item.capital?.[0]],
}));

console.log(result)

【讨论】:

    【解决方案2】:

    我修改了您的起始数据以修复一些语法错误:

    const array1 = [
        {
            name: {
                common: 'Afghanistan',
                official: 'Islamic Republic of Afghanistan',
            },
            capital: ['Kabul'],
        },
    ];
    
    const array2 = [
        {
            capital: ['Kabul'],
            population: 2837743,
        },
    ];
    

    根据要求,本次合并使用过滤器方法来匹配两个对象:

    const newArray = array1.map((arr1Obj) => {
        const capitalObj = array2.filter(
            (arr2Obj) =>
                JSON.stringify(arr1Obj.capital) === JSON.stringify(arr2Obj.capital)
        );
    
        return Object.assign(arr1Obj, ...capitalObj);
    });
    
    console.log(newArray);
    

    输出:

    [
        {
            name: {
            common: 'Afghanistan',
            official: 'Islamic Republic of Afghanistan',
            },
            capital: ['Kabul'],
            population: 2837743,
        },
    ];
    

    【讨论】:

      【解决方案3】:

      您可以这样做(我将capital 保留为数组,但如果不是这样会更简单):

      const arr1 = [
        {
          name: {
            common: 'Afghanistan',
            official: 'Islamic Republic of Afghanistan',
          },
          capital: ['Kabul'],
        },
        {
          name: {
            common: 'Albania',
            official: 'Republic of Albania',
          },
          capital: ['Tirana'],
        },
      ];
      
      const arr2 = [
        { capital: ['Tirana'], population: 2845955 },
        { capital: ['Kabul'], population: 2837743 },
      ];
      
      const populationByCapital = new Map();
      
      for (let el of arr2) {
        populationByCapital.set(el.capital[0], el.population);
      }
      
      const arr3 = arr1.map((el) => {
        return { ...el, population: populationByCapital.get(el.capital[0]) };
      });
      
      console.log(arr3);
      

      这应该给你:

      [
        {
          name: {
            common: 'Afghanistan',
            official: 'Islamic Republic of Afghanistan'
          },
          capital: [ 'Kabul' ],
          population: 2837743
        },
        {
          name: { common: 'Albania', official: 'Republic of Albania' },
          capital: [ 'Tirana' ],
          population: 2845955
        }
      ]
      

      请注意,如果有两个国家的首都名称相同,它可能会中断。


      编辑

      我现在看到您使用的是来自 restcountries.com 的 API,因此将 capital 更改为标量是您无法控制的。它是一个数组是有原因的——南非有 3 个首都。代码应该仍然可以工作,因为它是相同的 API,并且所有 3 个在两个端点中都以相同的顺序列出。

      但是有几个并发症。布维岛国显然没有首都,所以阵列将是空的,诺福克岛国和牙买加都以“金斯敦”为首都。要解决这两个问题,您可以更改键以包含国家名称和首都:

      const populationByCapital = new Map();
      
      for (let el of arr2) {
        populationByCapital.set(el.capital[0] + el.name.common, el.population);
      }
      
      const arr3 = arr1.map((el) => {
        return {
          ...el,
          population: populationByCapital.get(el.capital[0] + el.name.common),
        };
      });
      

      【讨论】:

        【解决方案4】:

        尝试执行此操作存在一些问题,因为您需要一种从语义角度处理合并的方法。您需要选择合并将匹配的字段。例如,如果两个国家有相同的人口,您不希望它们被匹配然后合并。

        您还需要注意和计划两个以上项目匹配的发生。立即想到的一个问题是这两个对象是否匹配但具有冲突的信息。即使他们真的是一对,这种情况也可能发生。人口随时间而变化。甚至像首都变化这样僵化的东西。

        在算法上,我将建议两种匹配方法。 两者中较简单的是有一个您想要匹配对象的可能字段列表。然后,您可以创建一个数组(字典或其他语言中的 hashmap),并按目前看到的值作为键。

        var capital_map = []
        for(country in countries1 + countries2){
         if (capital_map[country.capital]){
           //We have a match that we can then handle
         }else{
          //set up for possible matches down the array
          capital_map[country.capital] = country
        }
        

        在上面的例子中,我们只匹配大写字母。 您可以扩展它,如果匹配多个字段中的任何一个,则合并这两个元素或至少 N 个字段匹配。

        我要建议的另一种方法是创建一个定义一些加权匹配的函数。例如,重叠的字段中有多少部分是相同的,每个字段根据重要性进行加权,因此人口的重要性可能较低,但资本的重要性可能较高。

        我不知道您是否想更深入地了解两个数组的匹配嵌套,例如名称与官方名称,但我希望您至少对您使用的各种技术有更好的了解可以用于那个。 您可能拥有大写字母数组,因为您希望通过匹配但具有重叠字段并且不想担心解决方案的实体会出现问题。 (比如只取人口的平均值) 如果您确实打算将其扩展到两个以上的数据源,则可以执行两个以上的数组,例如进行投票,每个源对其答案进行投票。如果两个消息来源说首都是巴西利亚,而三个消息来源中只有一个说里约,那么您可以选择巴西利亚。

        【讨论】:

          猜你喜欢
          • 2021-03-08
          • 1970-01-01
          • 2020-02-04
          • 2015-01-26
          • 2012-08-06
          • 2019-08-31
          • 2019-06-14
          相关资源
          最近更新 更多