【问题标题】:How to combine/merge/intersect two arrays of objects in one loop?如何在一个循环中组合/合并/相交两个对象数组?
【发布时间】:2018-04-19 05:05:12
【问题描述】:

这段代码有效,但我觉得必须有更好的方法,而不必使用两次Array.find()

const people = [
  { id: 0, age: 99 },
  { id: 1, age: 54 },
  { id: 2, age: 54 }
];
const roles = [
  { pId: 0, responsabilites: ['make money'] },
  { pId: 1, responsabilites: ['make money', 'complain'] },
  { pId: 4, responsabilites: ['make the world a better place', 'sarcasmm'] },
];

let roomsAndOrders = people.filter(p => {
  return roles.find(r => r.pId === p.id);
});
roomsAndOrders = roomsAndOrders.map(p => {
  let r = roles.find(r => r.pId === p.id);
  return { ...r, ...p };
});
   
console.log(roomsAndOrders);

【问题讨论】:

    标签: javascript arrays filter ecmascript-6 javascript-objects


    【解决方案1】:

    只需使用一个.map。您原来的 filter 没有多大意义 - filter 从数组中过滤掉您不想要的元素,但它不会更改元素。您正在从您的 filter 函数返回对象,并且对象是真实的,因此 filter 实际上并没有做任何事情。

    编辑:或者只是反过来映射 - 一次从 roles 映射到 people,而不是从 people 映射到 roles

    const people = [
      { id: 0, age: 99 },
      { id: 1, age: 54 },
      { id: 2, age: 54 }
    ];
    const roles = [
      { pId: 0, responsabilites: ['make money'] },
      { pId: 1, responsabilites: ['make money', 'complain'] },
    ];
    
    const roomsAndOrders = roles.map(role => {
      const person = people.find(({ id }) => role.pId === id);
      return { ...role, ...person };
    });
    console.log(roomsAndOrders);

    要仅包含 ID 在两个数组中的对象,您必须改用 .reduce,因为 map 始终返回与原始数组中相同数量的元素:

    const people = [
      { id: 0, age: 99 },
      { id: 1, age: 54 },
      { id: 2, age: 54 }
    ];
    const roles = [
      { pId: 0, responsabilites: ['make money'] },
      { pId: 1, responsabilites: ['make money', 'complain'] },
      { pId: 4, responsabilites: ['make the world a better place', 'sarcasmm'] },
    ];
    
    const roomsAndOrders = roles.reduce((accum, role) => {
      const person = people.find(({ id }) => role.pId === id);
      if (person) accum.push({ ...role, ...person });
      return accum;
    }, []);
    console.log(roomsAndOrders);

    【讨论】:

    • 如果您注意到最后一个结果对象(54 岁)没有pId 键。这就是我使用filter 的原因。否则,我得到的对象没有匹配的id实际上我的也坏了。我修复了filter 函数
    • 并非所有浏览器都支持扩展运算符。如果您在代码中使用,请勾选 Use BabelJS / ES2015 复选框。
    • @GianfrancoP。如果您的原始结果不是您实际尝试的结果,请参阅我的编辑:只需映射相反的方式,这样您就不必filter
    • @GianfrancoP。 .find 将返回 null|object。当您执行{ ...a, ...b} 时,会处理空值,因此可以忽略。但为了安全起见,您始终可以使用.find(...) || {}
    • 最后一件事。如果任何对象在任一数组中都没有匹配的x.id == y.pid,我想丢弃它们怎么办?通过pId: 4查看新角色
    【解决方案2】:

    您可以使用哈希表在 O(n) 中做到这一点:

     const result = [], hash = {};
    
     for(const person of people)
       result.push(hash[person.id] = {...person});
    
    for(const role of roles)
      if(hash[role.pId])
        Object.assign(hash[role.pId], role);
    

    【讨论】:

      猜你喜欢
      • 2020-10-13
      • 2022-01-04
      • 1970-01-01
      • 1970-01-01
      • 2021-03-08
      • 1970-01-01
      • 2017-04-07
      相关资源
      最近更新 更多