通过键,javascript组合json数组

时间:2016-03-09 22:20:49

标签: javascript arrays json node.js algorithm

我需要组合两个json数组,由两个休息服务提供。具有相同" id"的条目属于一起。

json1 = [{id:1,name:'aaa'},
     {id:5,name:'ccc'},
     {id:3,name:'bbb'}
   ];

 json2 = [{id:3,parameter1:'x', parameter2:'y', parameter3:'z'},
     {id:1,parameter1:'u', parameter2:'v', parameter3:'w'},
     {id:5,parameter1:'q', parameter2:'w', parameter3:'e'}
    ];

我需要以下列方式在javascript中组合/复制/克隆json数组(我的模型在angular2中):

json3 = [{id:3,name:'bbb',parameter1:'x', parameter2:'y',   parameter3:'z'},
     {id:1,name:'aaa', parameter1:'u', parameter2:'v', parameter3:'w'},
     {id:5,name:'ccc', parameter1:'q', parameter2:'w', parameter3:'e'}
    ];

有没有办法将它们结合起来?参数名称未精确定义,需要使用可变参数向量。

我尝试用每个循环混合。对我来说非常难看。

12 个答案:

答案 0 :(得分:35)

两个单行:

用lodash:

res = _(json1).concat(json2).groupBy('id').map(_.spread(_.assign)).value();

在ES2015中:

res = json2.map(x => Object.assign(x, json1.find(y => y.id == x.id)));

答案 1 :(得分:6)

ES2015 georg的答案很有效;

    json1 = [
    {id:1, test: 0},
    {id:2, test: 0},
    {id:3, test: 0},
    {id:4, test: 0},
    {id:5, test: 0}
];

json2 = [
    {id:1, test: 1},
    {id:3, test: 1},
    {id:5, test: 1}
];

json1.map(x => Object.assign(x, json2.find(y => y.id == x.id)));

结果:

{id:1, test: 1},
{id:2, test: 0},
{id:3, test: 1},
{id:4, test: 0},
{id:5, test: 1}

答案 2 :(得分:3)

如果您想要编写它以便可以接收任意数量的数组,而不仅仅是2,那么您可以使用arguments,并执行以下操作:

var json1 = [{id:1,name:'aaa'},{id:5,name:'ccc'},{id:3,name:'bbb'}];

var json2 = [{id:3,parameter1:'x', parameter2:'y', parameter3:'z'},
 {id:1,parameter1:'u', parameter2:'v', parameter3:'w'},
 {id:5,parameter1:'q', parameter2:'w', parameter3:'e'}
];

function joinObjects() {
  var idMap = {};
  // Iterate over arguments
  for(var i = 0; i < arguments.length; i++) { 
    // Iterate over individual argument arrays (aka json1, json2)
    for(var j = 0; j < arguments[i].length; j++) {
       var currentID = arguments[i][j]['id'];
       if(!idMap[currentID]) {
          idMap[currentID] = {};
        }
       // Iterate over properties of objects in arrays (aka id, name, etc.)
      for(key in arguments[i][j]) {
          idMap[currentID][key] = arguments[i][j][key];
      }
    }
  }

  // push properties of idMap into an array
  var newArray = [];
  for(property in idMap) {
    newArray.push(idMap[property]);
  }
  return newArray;
}

var json3 = joinObjects(json1, json2);

Here is a working codepen.

答案 3 :(得分:1)

使用嵌套循环查找相应的元素并合并它们。

for (var i = 0; i < json1.length; i++) {
    var id = json1[i].id;
    for (var j = 0; j < json2.length; j++) {
        if (json2[j].id = id) {
            for (var key in json2[j]) {
                json1[i][key] = json2[j][key];
            }
            break;
        }
    }
}

最后,json1将包含组合元素。

上述代码假定json2的每个元素都与json1中的内容匹配。如果json2中可能有额外的元素,那么之后您需要额外的循环将这些元素复制到json1

答案 4 :(得分:1)

使用 forEach 过滤器,我们可以解决此问题。

&#13;
&#13;
vehicleArray1 = [{id:1, name: "a"},{id:2, name: "b"},{id:3, name:"c"}];
vehicleArray2 = [{id:1, type: "two wheeler"},{id:2, type: "four wheeler"},{id:3, type:"six wheeler"}];
var outArr = [];
vehicleArray1.forEach(function(value) {
    var existing = vehicleArray2.filter(function(v, i) {
        return (v.id == value.id);
    });
    if (existing.length) {
        value.type = existing[0].type;
        outArr.push(value)
    } else {
        value.type = '';
        outArr.push(value);
    }
});
console.log(outArr)
&#13;
&#13;
&#13;

答案 5 :(得分:1)

let json1 = [
    {id:1,name:'aaa'},
    {id:5,name:'ccc'},
    {id:3,name:'bbb'}
];

let json2 = [
    {id:3,parameter1:'x', parameter2:'y', parameter3:'z'},
    {id:1,parameter1:'u', parameter2:'v', parameter3:'w'},
    {id:5,parameter1:'q', parameter2:'w', parameter3:'e'}
];

let result = json1.map(obj => {
    let data = json2.find(item => item.id === obj.id);
    return {...obj, ...data}
});

答案 6 :(得分:1)

JavaScript:

let json1 = [
  { id: 1, name: 'aaa' },
  { id: 5, name: 'ccc' },
  { id: 3, name: 'bbb' }
];

let json2 = [
  { id: 3, parameter1: 'x', parameter2: 'y', parameter3: 'z' },
  { id: 1, parameter1: 'u', parameter2: 'v', parameter3: 'w' },
  { id: 5, parameter1: 'q', parameter2: 'w', parameter3: 'e' }
];

let json3 = [];

json1.forEach((j1) => {
  json2.forEach((j2) => {
    if (j1.id === j2.id) {
      json3.push({ ...j1, ...j2 });
    }
  });
});

console.log(JSON.stringify(json3));
.as-console-wrapper { top: 0; max-height: 100% !important; }

答案 7 :(得分:0)

这应该为你做。我希望代码本身有意义。如果两者都存在,则此示例将始终使json1值超过json2值。如果要更改它,则需要在最里面的循环中切换对象引用(src[i]obj[j])。

&#13;
&#13;
// Will take src, and merge in the contents of obj.
// Expects an array of objects for both.
// Will keep src values in favour of obj values.
function extend(src, obj) {
  
  // Loop the src, in this case json1
  for (var i = 0; i < src.length; i++) {
    
    // For every loop of json1, also loop json2
    for (var j = 0; j < obj.length; j++) {
      
      // If we have matching IDs operate on this pair
      if (src[i].id == obj[j].id) {
          
        // For every key in the object being merged in,
        // if the key exists in src, ignore new value.
        // if the doesn't exist in src, take the new value.
        for (var key in obj[j]) {
          src[i][key] = src[i].hasOwnProperty(key) ? src[i][key] : obj[j][key];
        }
        
        // We found our matching pair, so break out of the json2 loop
        break;
        
      }
      
    }
    
  }
  
  return src;
}

// -------------------------------------------

var json1 = [{
  id: 1,
  name: 'aaa'
},{
  id: 5,
  name: 'ccc'
},{
  id: 3,
  name: 'bbb'
}];

var json2 = [{
  id: 3,
  parameter1: 'x', 
  parameter2: 'y', 
  parameter3: 'z'
},{
  id: 1,
  parameter1: 'u', 
  parameter2: 'v', 
  parameter3: 'w'
},{
  id: 5,
  parameter1: 'q', 
  parameter2: 'w', 
  parameter3: 'e'
}];

var json3 = extend(json1, json2);

// ---------------------------------------------

var pre = document.getElementById('out');
pre.innerHTML = JSON.stringify(json3);
&#13;
<pre id="out"></pre>
&#13;
&#13;
&#13;

答案 8 :(得分:0)

这是一种首先构建由 id (稀疏数组)键入的索引,以检测和组合具有匹配的 id 值的对象,然后最终连接回来的方法进入正常数组:

json3 = json1.concat(json2).reduce(function(index, obj) {
    if (!index[obj.id]) {
        index[obj.id] = obj;
    } else {
        for (prop in obj) {
            index[obj.id][prop] = obj[prop];
        }
    }
    return index;
}, []).filter(function(res, obj) {
    return obj;
});

json1 = [
    {id:1,name:'aaa'},
    {id:5,name:'ccc'},
    {id:3,name:'bbb'}
];

json2 = [
    {id:3,parameter1:'x', parameter2:'y', parameter3:'z'},
    {id:1,parameter1:'u', parameter2:'v', parameter3:'w'},
    {id:5,parameter1:'q', parameter2:'w', parameter3:'e'}
];

json3 = json1.concat(json2).reduce(function(index, obj) {
    if (!index[obj.id]) {
        index[obj.id] = obj;
    } else {
        for (prop in obj) {
            index[obj.id][prop] = obj[prop];
        }
    }
    return index;
}, []).filter(function(res, obj) {
    return obj;
});

document.write('<pre>', JSON.stringify(json3, null, 4), '</pre>');

如果您的浏览器支持Object.assign

json3 = json1.concat(json2).reduce(function(index, obj) {
    index[obj.id] = Object.assign({}, obj, index[obj.id]);
    return index;
}, []).filter(function(res, obj) {
    return obj;
});

答案 9 :(得分:0)

这是使用 object-lib 的通用解决方案。

优点是您可以完全控制对象的合并方式,并且支持嵌套和多个嵌套的 groupBy。

// const objectLib = require('object-lib');

const { Merge } = objectLib;

const json1 = [{ id: 1, name: 'aaa' }, { id: 5, name: 'ccc' }, { id: 3, name: 'bbb' }];
const json2 = [{ id: 3, parameter1: 'x', parameter2: 'y', parameter3: 'z' }, { id: 1, parameter1: 'u', parameter2: 'v', parameter3: 'w' }, { id: 5, parameter1: 'q', parameter2: 'w', parameter3: 'e' }];

const groupById = Merge({ '[*]': 'id' });
console.log(groupById(json1, json2));
// => [ { id: 1, name: 'aaa', parameter1: 'u', parameter2: 'v', parameter3: 'w' }, { id: 5, name: 'ccc', parameter1: 'q', parameter2: 'w', parameter3: 'e' }, { id: 3, name: 'bbb', parameter1: 'x', parameter2: 'y', parameter3: 'z' } ]

const o1 = [{ id: 1, children: [{ type: 'A' }, { type: 'C' }] }, { id: 5 }];
const o2 = [{ id: 1, children: [{ type: 'A' }, { type: 'B' }] }, { id: 3 }];

console.log(groupById(o1, o2));
// => [ { id: 1, children: [ { type: 'A' }, { type: 'C' }, { type: 'A' }, { type: 'B' } ] }, { id: 5 }, { id: 3 } ]

const groupByCustom = Merge({
  '[*]': 'id',
  '[*].children[*]': 'type'
});
console.log(groupByCustom(o1, o2));
// => [ { id: 1, children: [ { type: 'A' }, { type: 'C' }, { type: 'B' } ] }, { id: 5 }, { id: 3 } ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-lib@2.0.0"></script>

免责声明:我是object-lib

的作者

答案 10 :(得分:0)

the two one-liners 的堆栈片段

洛达什

const json1 = [{ id: 1, name: 'aaa' }, { id: 3, name: 'bbb' },
  { id: 5, name: 'ccc' }];
const json2 = [{ id: 3, parameters: 'xyz' },
  { id: 5, parameters: 'qwe' }, { id: 1, parameters: 'uvw' }];
console.log('json1 BEFORE:\n' + JSON.stringify(json1));

const result_Lodash =
  _(json1).concat(json2).groupBy('id').map(_.spread(_.assign)).value();
console.log('Result, Lodash:\n' + JSON.stringify(result_Lodash));
console.log('json1 AFTER:\n' + JSON.stringify(json1));
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src=
"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.js"></script>


Object.assign

const json1 = [{ id: 1, name: 'aaa' }, { id: 3, name: 'bbb' },
  { id: 5, name: 'ccc' }];
const json2 = [{ id: 3, parameters: 'xyz' },
  { id: 5, parameters: 'qwe' }, { id: 1, parameters: 'uvw' }];
console.log('json2 BEFORE:\n' + JSON.stringify(json2));

const result_Object_assign =
  json2.map(x => Object.assign(x, json1.find(y => y.id === x.id)));
console.log('Object.assign:\n' + JSON.stringify(result_Object_assign));
console.log('json2 AFTER:\n' + JSON.stringify(json2));
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src=
"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.js"></script>

值得指出的是,对于这两种解决方案,第一个的内容 / left 数组已更改。
运行代码片段以查看它。
例如,Object.assign(x, json1.find(y => y.id === x.id)) 复制 将数据复合到 x 中的对象 json2json2 中的对象是 因此通过.map()更新。
标识符 result_Object_assign 实际上只是另一个指针 指向与 json2 指向的数组完全相同的数组 - 没有新对象 已创建!


Object.assign 不改变输入数组
如果您不想更改任何输入数组,只需创建一个新的 数组,如下图:

const json1 = [{ id: 1, name: 'aaa' }, { id: 3, name: 'bbb' },
  { id: 5, name: 'ccc' }];
const json2 = [{ id: 3, parameters: 'xyz' },
  { id: 5, parameters: 'qwe' }, { id: 1, parameters: 'uvw' }];
console.log('json2 BEFORE:\n' + JSON.stringify(json2));

const result_Object_assign =
  json2.map(x => Object.assign({}, x, json1.find(y => y.id === x.id)));
console.log('Object.assign:\n' + JSON.stringify(result_Object_assign));
console.log('json2 AFTER:\n' + JSON.stringify(json2));
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src=
"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.js"></script>

答案 11 :(得分:0)

the concat-reduce answers 的堆栈片段

结果 1:使用 reduce 并匹配 ID
先将两个数组串联成一个数组,然后检测合并 具有匹配 id 的对象。最后过滤掉所有 null 值。

结果 2:使用 reduce 和 Object.assign

const json1 = [{id:1,name:'aaa'},{id:3,name:'bbb'},{id:5,name:'ccc'}];
const json2 =
  [{id:3,parameters:'xyz'},{id:5,parameters:'qwe'},{id:1,parameters:'uvw'}];
const json7 = json1.concat(json2);
console.log(' json7:\n'+JSON.stringify(json7));

const Result_1 =
  json7.reduce((accumulator, obj) => {
    if (!accumulator[obj.id]) {
      accumulator[obj.id] = obj;
    } else {
      for (proprty in obj) { accumulator[obj.id][proprty] = obj[proprty];}
    }
    return accumulator;
  }, []).filter(x => x);
console.log('\n Result_1:\n' + JSON.stringify(Result_1));

const Result_2 =
  json1.concat(json2).reduce((accumulator, obj) => {
    accumulator[obj.id] = Object.assign({}, accumulator[obj.id], obj);
    return accumulator;
  }, []).filter(x => x);
console.log('\n Result_2:\n' + JSON.stringify(Result_2));
.as-console-wrapper { max-height: 100% !important; top: 0; }

参考: