相当于SQL与Javascript对象数组的完全连接

Equivalent of a SQL Full Join with Arrays of Javascript Objects

本文关键字:连接 数组 对象 SQL Javascript 相当于      更新时间:2023-09-26

我知道有很多"在JS中合并两个对象数组"的问题,我已经阅读了其中的大部分。与我正在尝试做的事情最相似的几个是:

如何动态合并两个JavaScript对象的属性?

原生javascript -合并两个对象数组

如何合并两个对象数组JSON数据上的SQL样式JOIN

我的问题是不同的,因为我试图做一个完整的SQL连接,其中数组将是不同的大小,并将有新的列。

例如:

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"}];
所需输出:

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"}];

因此,类似于完整的SQL连接,我希望输出JSON包含所有列,当有匹配时匹配,但如果第二个JSON中的键:值对不匹配第一个对象中的任何一个,则生成新行。

到目前为止我所拥有的如下。它一般工作,但有几个问题。我在对一个特定的预定义值进行归并,这对函数找出匹配的值在哪里是很好的。此外,如果我向JSON2添加一个以上的新属性列(即:如果JSON2有颜色和英寸,但没有颜色、英寸和名称,它可以工作。)因为我只是把一个属性哈希到另一个属性

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]);
    }
}

我想这可能是你想要的,…

它可以被优化等,但希望这是一个开始。

哦,为了简单起见,我还使用了Object。赋值,所以要注意,对于旧的浏览器,你可能需要一个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)); });

我是这样处理数组的

  1. 使用Array.prototype.map通过复制JSON2中对应的键/值来从JSON1创建一个新的数组

  2. 还跟踪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;}

让我知道你的反馈,如果这对你有效。谢谢!