【问题标题】:Equivalent of a SQL Full Join with Arrays of Javascript Objects等效于带有 Javascript 对象数组的 SQL 完全连接
【发布时间】:2017-02-27 02:29:31
【问题描述】:

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

How can I merge properties of two JavaScript objects dynamically?

Native javascript - merge two arrays of objects

How to merge two array of objects SQL style JOIN on JSON data

我的问题不同,因为我正在尝试进行完整的 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]);
    }
}

【问题讨论】:

  • 请注意,您的问题中没有显示 no JSON。您的输入和输出都只是对象数组。
  • @Acoustic77 仍在等待您对以下答案的想法 :)
  • 抱歉,看到了你的回答,但一位朋友能够帮助我在线性时间内完成,所以我会尝试发布该答案
  • @Acoustic77 我很想知道你在线性时间内得到的答案——你能把那个贴出来吗?我相信我可以从中学到一些东西,谢谢!

标签: javascript arrays json


【解决方案1】:

我想这可能是你的追求,..

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

哦,为了简单起见,我也在使用 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)); });

【讨论】:

    【解决方案2】:

    这就是我对数组所做的:

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

    如果这对您有用,请告诉我您的反馈。谢谢!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-10
      • 2016-03-03
      • 1970-01-01
      • 2012-01-06
      • 2023-04-08
      • 1970-01-01
      相关资源
      最近更新 更多