简体   繁体   English

与Javascript对象数组的SQL完全连接的等价物

[英]Equivalent of a SQL Full Join with Arrays of Javascript Objects

I know that there are quite a lot of "Merge two arrays of objects in JS" questions, and I've read most of them. 我知道有很多“在JS中合并两个对象数组”的问题,我已经阅读了大部分内容。 a few most similar to what I'm trying to do are: 一些与我正在尝试做的最相似的是:

How can I merge properties of two JavaScript objects dynamically? 如何动态合并两个JavaScript对象的属性?

Native javascript - merge two arrays of objects 原生javascript - 合并两个对象数组

How to merge two array of objects SQL style JOIN on JSON data 如何 在JSON数据上 合并 SQL样式JOIN的 两个对象数组

My issue is different because I'm trying to do a full SQL join, where the arrays will be different sizes, and will have new columns. 我的问题不同,因为我正在尝试进行完整的SQL连接,其中数组的大小不同,并且会有新的列。

For example: 例如:

JSON1 = [{Color:"Blue", ID:"15", Size:"Large",Shape:"Square"},
         {Color:"Red", ID:"9", Size:"Medium",Shape:"Circle"},
         {Color:"Red", ID:"2", Size:"Large",Shape:"Triangle"},
         {Color:"Yellow", ID:"3", Size:"Small",Shape:"Square"}];

JSON2 = [{Color:"Blue", Name:"Henry", Inches:"51"},
         {Color:"Red", Name:"Jane", Inches:"7"},
         {Color:"Pink", Name:"Jack", Inches:"14"}];

Desired Output: 期望的输出:

OUTPUT =[{Color:"Blue", ID:"15", Size:"Large",Shape:"Square",Name:"Henry", Inches:"51"},
         {Color:"Red", ID:"9", Size:"Medium",Shape:"Circle",Name:"Jane", Inches:"7"},
         {Color:"Red", ID:"2", Size:"Large",Shape:"Triangle",Name:"Jane", Inches:"7"},
         {Color:"Yellow", ID:"3", Size:"Small",Shape:"Square",Name:null, Inches:null},
         {Color:"Pink", ID:null, Size:null,Shape:null,Name:"Jack", Inches:"14"}];

So, similar to a full SQL join, I want the output JSON to contain all columns, matched when there is a match, but a new row if a key:value pair in the second JSON doesn't match any of the ones in any of the objects in the first. 因此,类似于完整的SQL连接,我希望输出JSON包含匹配时匹配的所有列,但是如果第二个JSON中的键:值对与任何列中的任何一个都不匹配,则需要新行第一个中的对象。

What I have so far is below. 我到目前为止的内容如下。 It generally works but has a couple issues. 它通常有效,但有几个问题。 I'm merging on a specific pre-defined value, and it would be nice for the function to figure out where the matching value was. 我正在合并一个特定的预定义值,并且函数可以找出匹配值的位置。 Also, my function fails if I add more than one new property column to JSON2(ie it works if JSON2 has Color and Inches, but not Color, Inches, and Name.) Because I'm just hashing one property to one other. 此外,如果我向JSON2添加多个新属性列,我的函数将失败(即,如果JSON2具有Color和Inches,但不是Color,Inches和Name,则它可以工作。)因为我只是将一个属性散列到另一个属性。

var hash={};
for(var e in JSON2){
    hash[JSON2[e]["Color"]]= JSON2[e]["Inches"];
}
var trackHash = hash;
for(var k in JSON1){
    JSON1[k]["Inches"] = hash[JSON1[k]["Color"]];
    if(hash[JSON1[k]["Color"]]===undefined){
        delete trackHash[JSON1[k]["Color"]];
    }
}
for(var obj in JSON2){
    if(trackHash[JSON2[obj]["Color"]]!==undefined){
        JSON1.push(JSON2[obj]);
    }
}

I think this might be what your after,.. 我想这可能是你的事,...

It could be optimized etc, but hopefully this is a start. 它可以被优化等,但希望这是一个开始。

Oh, for simplicity I'm also using Object.assign, so be aware for old browsers you might need a polyfill, or use something like lodash. 哦,为了简单起见,我也使用了Object.assign,所以要注意旧浏览器,你可能需要一个polyfill,或者使用像lodash这样的东西。

 var JSON1 = [{Color:"Blue", ID:"15", Size:"Large",Shape:"Square"}, {Color:"Red", ID:"9", Size:"Medium",Shape:"Circle"}, {Color:"Red", ID:"2", Size:"Large",Shape:"Triangle"}, {Color:"Yellow", ID:"3", Size:"Small",Shape:"Square"}]; var JSON2 = [{Color:"Blue", Name:"Henry", Inches:"51"}, {Color:"Red", Name:"Jane", Inches:"7"}, {Color:"Pink", Name:"Jack", Inches:"14"}]; function fullJoin(a, b) { var r = []; a.forEach(function (a) { var found = false; b.forEach(function (b) { if (a.Color === b.Color) { var j = Object.assign(a, b); r.push(j); found = true; } }) if (!found) r.push(a); }); b.forEach(function (b) { var found = false; a.forEach(function (a) { if (a.Color === b.Color) found = true; }); if (!found) r.push(b); }); return r; } var a = fullJoin(JSON1, JSON2); a.forEach(function (a) { console.log(JSON.stringify(a)); }); 

So here is what I did with the arrays: 所以这就是我对数组做的事情:

  1. Use Array.prototype.map to create a new array from JSON1 by copying in the key/value's for the corresponding similar keys in JSON2 使用Array.prototype.map以创建一个新的阵列JSON1通过在键/值的拷贝在相应的相似键JSON2

  2. Also tracked the keys in JSON2 that is not in JSON1 and added it to the result thereafter. 还追踪中的键JSON2不在JSON1并且此后它添加到结果。

 var JSON1 = [{Color:"Blue", ID:"15", Size:"Large",Shape:"Square"}, {Color:"Red", ID:"9", Size:"Medium",Shape:"Circle"}, {Color:"Red", ID:"2", Size:"Large",Shape:"Triangle"}, {Color:"Yellow", ID:"3", Size:"Small",Shape:"Square"}]; var JSON2 = [{Color:"Blue", Name:"Henry", Inches:"51"}, {Color:"Red", Name:"Jane", Inches:"7"}, {Color:"Pink", Name:"Jack", Inches:"14"}]; var excluded = {}; // Join JSON2 to JSON1 // also track elements in JSON2 not in JSON1 var result = JSON1.map(function(a) { JSON2.forEach(function(element, index, array) { if (a.Color === element.Color) { Object.keys(element).forEach(function(key) { a[key] = element[key]; }); } else { this.visited = this.visited + 1 || 0; if(this.visited == array.length) { this.found = this.found || []; this.found.push(element); } } }, this); this.visited = 0; return a; }, excluded); // add elements in JSON2 not in JSON1 if(excluded.found) { excluded.found.forEach(function(element) { result.push(element); }); } console.log(result); 
 .as-console-wrapper{top:0;max-height:100%!important;} 

Let me know your feedback if this worked for you. 如果这对您有用,请告诉我您的反馈。 Thanks! 谢谢!

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

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