【问题标题】:Merge two arrays with key , and the second array being an object inside the 1st array用 key 合并两个数组,第二个数组是第一个数组中的对象
【发布时间】:2021-04-08 18:16:18
【问题描述】:

假设我有 2 个数组 arr1,arr2:

var arr1 = [{id:1, name:2}, {id:2, name:3}, {id:3, name:2}];
var arr2 = [{orgid:2, desc:'2'},{orgid:1, desc:'1'},{orgid:1, desc:'3'}]


我想实现以下目标:

var arr3 = [{id:1, name:2, org: [{desc:'1'},{ desc:'3'}]},{id:2, name:3, org: {desc:'2'}} , {id:3, name:2, org: []}]

我尝试了以下方法:

const map = new Map();
arr1.forEach(item => map.set(item.id, item));
arr2.forEach(item => map.set(item.orgid, {...map.get(item.orgid), ...item}));

这给了我类似的东西:

[{"id":1,"name":2,"orgid":1,"desc":"1"}, {"id":2,"name":3,"orgid":2,"desc":"2"}]

所以 id 和 orgId 是相同的,它是我用来合并数组的键。

有一个细微的变化,我可能期望 arr2 中相同 orgId 的多个对象,这应该映射到 arr3 中的 org 数组。

arr2 中也可能不存在 orgId,这将在 arr3 中填充一个空白 org[]

【问题讨论】:

  • 你试过什么?发布它,以便其他人可以帮助您。
  • 用我尝试过的方法编辑了帖子,但是我正在尝试创建 arr3
  • 检查我的答案
  • 请再次检查我的答案。我已经更新了。

标签: javascript


【解决方案1】:

您可以使用Map 收集组织并使用其他属性映射数组。

const
    arr1 = [{ id: 1, name: 2 }, { id: 2, name: 3 }],
    arr2 = [{ orgid: 2, desc: '2' }, { orgid: 1, desc: '1' }, { orgid: 1, desc: '3' }],
    map2 = arr2.reduce((m, { orgid, ...o }) => m.set(orgid, m.has(orgid)
        ? [].concat(m.get(orgid), o)
        : o
    ), new Map),
    result = arr1.map(o => ({ ...o, org: map2.get(o.id) || [] }));
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 但是如果我有 arr2 像 var arr2 = [{orgid:2, desc:'2'},{orgid:1, desc:'1'},{orgid:1, desc :'3'}],那么它只映射 arr3 中的 orgid:1, desc:'3',我试图看看我是否可以将两个对象映射为一个数组
  • 它从第一个数组中获取所有项目。不匹配的项目你想要什么结果?
  • [ { "id": 1, "name": 2, "org": [{ "desc": "1" }, }, { "id": 2, "name": 3、“org”:{“desc”:“2”}}]
  • 假设,您想要所有匹配的项目,如果数组中有多个或单个对象。请参阅编辑。
  • 是的,这就像一个魅力,但是对于所有不匹配的项目,我想要一个空的 org[]
【解决方案2】:

您可以使用 rest 语法删除 orgid 属性并将其余属性添加到另一个键下。

var arr1 = [{id:1, name:2}, {id:2, name:3}];
var arr2 = [{orgid:2, desc:'2'},{orgid:1, desc:'1'}]
const map = new Map();
arr1.forEach(item => map.set(item.id, item));
arr2.forEach(({orgid, ...rest}) => map.set(orgid, {...map.get(orgid), org: rest}));
console.log([...map.values()]);

【讨论】:

    【解决方案3】:

    您可以缓存组织,然后在映射时查找它们。

    const
      arr1 = [ { id: 1, name: 2 }, { id: 2, name: 3 } ],
      arr2 = [ { orgid: 2, desc: '2' }, { orgid: 1, desc: '1' } ],
      orgs = arr2.reduce((acc, { orgid, ...rest }) => ({ ...acc, [orgid]: { ...rest } }), {}),
      arr3 = arr1.map(({ id, ...rest }) => ({ id, ...rest, org: orgs[id] }));
    
    console.log(arr3);
    .as-console-wrapper { top: 0; max-height: 100% !important; }

    【讨论】:

      【解决方案4】:

      这应该可行:

      arr1.map(el => ({
        ...el,
        org: ({ desc: arr2.find(o => o.orgid === el.id)?.desc || null })
      }))
      

      var arr1 = [{id:1, name:2}, {id:2, name:3}];
      var arr2 = [{orgid:2, desc:'2'},{orgid:1, desc:'1'}]
      
      console.log(arr1.map(el => ({
        ...el,
        org: ({ desc: arr2.find(o => o.orgid === el.id)?.desc || null })
      })))

      映射第一个数组的元素,并在org 属性内将第二个数组中第一个匹配项的desc 分配给每个数组,其中orgid 等于当前元素的id。
      如果它没有找到匹配项,它会分配null(你还没有指定在没有匹配项的情况下应该发生什么)。

      通过查看所需的结果,我猜这就是您所追求的。

      如果您想保留来自第二个数组的对象中的所有内容,除了orgid 属性,您可以在第二个数组上映射解构,并由第一个数组的id 过滤:

      arr1.map(el => ({
        ...el,
        org: arr2.filter(o => o.orgid === el.id).map(({orgid, ...r}) => r)[0] || {}
      }))
      

      var arr1 = [{id:1, name:2}, {id:2, name:3}, {id: 5, name: 'no org matched'}];
      var arr2 = [{orgid:2, desc:'2', foo: 'bar'},{orgid:1, desc:'1', foo: 'baz'}]
      
      console.log(arr1.map(el => ({
        ...el,
        org: arr2.filter(o => o.orgid === el.id).map(({orgid, ...r}) => r)[0] || null
      })))

      建议从对象数组中删除属性通常被认为是一种反模式,尤其是当属性值是原始值时,原因有两个:

      1. 您在尺寸上获得的优化并不能证明计算成本是合理的
      2. 如果您以后需要删除的道具(现在可以在父母的id 中找到),您将不得不做更多的JavaScript 体操来获得它。把它放在那里会更好(而且非常便宜)。

      您尝试做的唯一有效用例是当您要删除的属性包含大量信息(使您的数据对于您可能正在使用的其他一些操作而言过于繁重)或安全性时原因(当您将此数据提供给不应访问 orgid 的某人或某物时)。
      这两个似乎都不是你的情况。

      【讨论】:

      • 这段代码有效,但是如果我有除 desc 之外的更多字段,
      • 回到过去并在不遗漏重要细节的情况下提出问题怎么样?我在答案中添加了第二种情况,它使用解构将除orgid 属性之外的所有内容保留在第二个数组中。
      【解决方案5】:

      解决办法如下:

      var arr1 = [{id:1, name:2}, {id:2, name:3}];
      var arr2 = [{orgid:2, desc:'2'},{orgid:1, desc:'1'}]
      
      var arr3 = arr1.map(item => ({
            ...item,
            org: ({ desc: arr2.find(o => o.orgid === item.id)?.desc || null })
          }))
      

      var arr1 = [{id:1, name:2}, {id:2, name:3}];
      var arr2 = [{orgid:2, desc:'2'},{orgid:1, desc:'1'}]
      
      const arr3 = arr1.map(item => ({
        ...item,
        org: ({ desc: arr2.find(o => o.orgid === item.id)?.desc || null })
      }))
      
      console.log(arr3)

      【讨论】:

        猜你喜欢
        • 2012-03-31
        • 2019-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-11
        相关资源
        最近更新 更多