简体   繁体   English

在Javascript中的多个键上连接对象数组

[英]Join arrays of objects on a mutiple key in Javascript

I have two arrays of objects: 我有两个对象数组:

A = [
    { id1: "1", id2: "a", p1: "3", p2: "4" },
    { id1: "1", id2: "b", p1: "5", p2: "6" },
    { id1: "2", id2: "a", p1: "7", p2: "8" },
    { id1: "2", id2: "b", p1: "9", p2: "10" }
];


B = [
    { id1: "1", id2: "a", p3: "13", p4: "14" },
    { id1: "1", id2: "b", p3: "15", p4: "16" },
    { id1: "2", id2: "a", p3: "17", p4: "18" },
    { id1: "2", id2: "b", p3: "19", p4: "20" }
];

I need a function that makes an inner join between the two objects based on the two properties id1 and id2 , making a union of the other properties ( properties names are never equal except for id1 and id2 ) In other words I need as a result: 我需要一个函数,该函数基于两个属性id1id2在两个对象之间进行内部id1id2其他属性( 除了id1id2属性名称永远不会相等 )换句话说,我需要:

C = [
    { id1: "1", id2: "a", p1: "3", p2: "4", p3: "13", p4: "14" },
    { id1: "1", id2: "b", p1: "5", p2: "6", p3: "15", p4: "16" },
    { id1: "2", id2: "a", p1: "7", p2: "8", p3: "17", p4: "18" },
    { id1: "2", id2: "b", p1: "9", p2: "10", p3: "19", p4: "20" }
];

In here I can find a way to make the join using one single key. 在这里,我可以找到一种使用一个键进行联接的方法。 I need an extention for the multiple keys case. 我需要扩展多个键的情况。

http://learnjsdata.com/combine_data.html http://learnjsdata.com/combine_data.html

You can make a lookup based on one array with a composite key from the two ids, then loop through the second, look up the merged key, and create a new object from the two items using Object.assign() . 您可以使用两个ID中的复合键基于一个数组进行查找,然后遍历第二个,查找合并的键,并使用Object.assign()从这两个项中创建一个新对象。 This will allow you to make the list without having an O(n²) solution of searching A for every item in B 这样您就可以列出列表,而无需O(n²)解决方案来搜索A中的每个项目的B

 let A=[ {id1:"1", id2:"a", p1:"3", p2:"4"}, {id1:"1", id2:"b", p1:"5", p2:"6"}, {id1:"2", id2:"a", p1:"7", p2:"8"}, {id1:"2", id2:"b", p1:"9", p2:"10"} ] let B=[{id1:"1", id2:"a", p3:"13", p4:"14"}, {id1:"1", id2:"b", p3:"15", p4:"16"}, {id1:"2", id2:"a", p3:"17", p4:"18"}, {id1:"2", id2:"b", p3:"19", p4:"20"} ] let lookup = A.reduce((obj, item) => { obj[`${item.id1}_${item.id2}`] = item // key in form of id1_id2 return obj }, {}) let merged = B.reduce((arr, item) => { if (lookup[`${item.id1}_${item.id2}`]) { arr.push(Object.assign({}, lookup[`${item.id1}_${item.id2}`], item)) } return arr }, []) console.log(merged) 

You just need to make sure the separator of the key ( _ here) doesn't exist in you ids. 您只需要确保ID中不存在键的分隔符(此处为_ )即可。 If that's a problem, you could make a nested object with lookups like obj[id1][id2] : 如果这是一个问题,则可以使用obj[id1][id2]类的查询来创建嵌套对象:

let lookup = A.reduce((obj, item) => {
    if (!obj[item.id1]) obj[item.id1] = {}
    obj[item.id1][item.id2] = item
    return obj
}, {} )

and adjust the reduce() callback to fit. 并调整reduce()回调以适合。

If the array's are very large, using a lookup like @MarkMeyer shows would might be better option. 如果数组是非常大的,使用查找类似@MarkMeyer节目 可能是更好的选择。 But for smaller arrays doing a simple map, array spread & find works fine. 但是对于较小的数组做一个简单的映射,数组散布和查找工作正常。

As pointed out by @user11299053 this is not the equivalent of an inner join, maybe a left join instead,.. So I'll leave this as is, it might be useful. 正如@ user11299053所指出的,这不等效于内部联接,而可能等效于左联接。.因此,我将其保留不变,这可能会很有用。 :) :)

 const A=[ {id1:"1", id2:"a", p1:"3", p2:"4"}, {id1:"1", id2:"b", p1:"5", p2:"6"}, {id1:"2", id2:"a", p1:"7", p2:"8"}, {id1:"2", id2:"b", p1:"9", p2:"10"} ]; const B=[ {id1:"1", id2:"a", p3:"13", p4:"14"}, {id1:"1", id2:"b", p3:"15", p4:"16"}, {id1:"2", id2:"a", p3:"17", p4:"18"}, {id1:"2", id2:"b", p3:"19", p4:"20"} ]; const merged = B.map(item => ({ ...A.find( f => f.id1 === item.id1 && f.id2 === item.id2), ...item })); console.log(merged); 

Both provided answers DO NOT deliver expected result ( inner join which is supposed to contain only matching items from both data sets). 提供的两个答案均未提供预期的结果( 内部联接应该包含两个数据集中的匹配项)。

I have somewhat extended input arrays in order to demonstrate the difference of output for provided answers and mine: 我有一些扩展的输入数组,以演示提供的答案和我的输出的区别:

 const A = [ {id1:"1", id2:"a", p1:"3", p2:"4"}, {id1:"1", id2:"b", p1:"5", p2:"6"}, {id1:"2", id2:"a", p1:"7", p2:"8"}, {id1:"2", id2:"b", p1:"9", p2:"10"}, {id1:"3", id2:"c", p1:"1", p2:"3"} ]; const B = [ {id1:"1", id2:"a", p3:"13", p4:"14"}, {id1:"1", id2:"b", p3:"15", p4:"16"}, {id1:"2", id2:"a", p3:"17", p4:"18"}, {id1:"2", id2:"b", p3:"19", p4:"20"}, {id1:"4", id2:"k", p3:"11", p4:"13"} ]; const innerJoined = A.reduce((result, itemA) => { const itemB = B.find(itemB => itemB.id1 == itemA.id1 && itemB.id2 == itemA.id2); if(itemB) result.push({...itemA, ...itemB}); return result; }, []); console.log(innerJoined); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM