You can use reduce() and concat() methods for this.
const data = [{"meine_frage":"hier kommt die antwort","ne_andere_frage":"ne andere antwort","was_willst_du":"alles","mehr_zur_auswahl":["einiges","vieles und","gär nix"]},{"meine_frage":"tom & jerry","ne_andere_frage":"mickey maus","was_willst_du":"oder","mehr_zur_auswahl":["manches","einiges","vieles und","gär nix"]},{"meine_frage":"dick und doof","ne_andere_frage":"minnie muas","was_willst_du":"nichts","mehr_zur_auswahl":["gär nix"]}]
// Use the `reduce` method to accumulate results into a single object.
const result = data.reduce(function(r, e) {
// Iterate over each key in the current object.
return Object.keys(e).forEach(function(k) {
// Check if the key exists in the result object.
if(!r[k]) r[k] = [].concat(e[k]) // If the key doesn't exist, initialize it as an array containing the value from the current object.
else r[k] = r[k].concat(e[k]) // If the key does exist, concatenate the existing array with the value from the current object.
}), r // Return the updated result object for the next iteration.
}, {}) // Start with an empty object `{}` as the initial value of `result`.
console.log(result)
Answer from Nenad Vracar on Stack OverflowYou can use reduce() and concat() methods for this.
const data = [{"meine_frage":"hier kommt die antwort","ne_andere_frage":"ne andere antwort","was_willst_du":"alles","mehr_zur_auswahl":["einiges","vieles und","gär nix"]},{"meine_frage":"tom & jerry","ne_andere_frage":"mickey maus","was_willst_du":"oder","mehr_zur_auswahl":["manches","einiges","vieles und","gär nix"]},{"meine_frage":"dick und doof","ne_andere_frage":"minnie muas","was_willst_du":"nichts","mehr_zur_auswahl":["gär nix"]}]
// Use the `reduce` method to accumulate results into a single object.
const result = data.reduce(function(r, e) {
// Iterate over each key in the current object.
return Object.keys(e).forEach(function(k) {
// Check if the key exists in the result object.
if(!r[k]) r[k] = [].concat(e[k]) // If the key doesn't exist, initialize it as an array containing the value from the current object.
else r[k] = r[k].concat(e[k]) // If the key does exist, concatenate the existing array with the value from the current object.
}), r // Return the updated result object for the next iteration.
}, {}) // Start with an empty object `{}` as the initial value of `result`.
console.log(result)
You could use reduce method by passing a callback function as parameter.
The algorithm is follow: if final object already contains one key then you should initialize the key's value with an empty array. Otherwise, you should append to array value from all items from the array.
let data = [{"meine_frage":"hier kommt die antwort","ne_andere_frage":"ne andere antwort","was_willst_du":"alles","mehr_zur_auswahl":["einiges","vieles und","gär nix"]},{"meine_frage":"tom & jerry","ne_andere_frage":"mickey maus","was_willst_du":"oder","mehr_zur_auswahl":["manches","einiges","vieles und","gär nix"]},{"meine_frage":"dick und doof","ne_andere_frage":"minnie muas","was_willst_du":"nichts","mehr_zur_auswahl":["gär nix"]}]
let result = data.reduce(function(obj, item){
Object.keys(item).forEach(function(key){
if(!obj[key]) obj[key] = [].concat(item[key])
else {
if(Array.isArray(item[key]))
obj[key].push(...item[key])
else
obj[key].push(item[key]);
}
});
return obj;
},{});
console.log([result]);
javascript - Concatenate two JSON objects - Stack Overflow
javascript - Merge Objects With Same JSON Key - Stack Overflow
How to join two JavaScript Objects, without using JQUERY - Stack Overflow
merge two json object based on key value in javascript - Stack Overflow
Videos
Based on your description in the comments, you'd simply do an array concat():
var jsonArray1 = [{'name': "doug", 'id':5}, {'name': "dofug", 'id':23}];
var jsonArray2 = [{'name': "goud", 'id':1}, {'name': "doaaug", 'id':52}];
jsonArray1 = jsonArray1.concat(jsonArray2);
console.log(jsonArray1)
// [{'name': "doug", 'id':5}, {'name': "dofug", 'id':23}, {'name': "goud", 'id':1}, {'name': "doaaug", 'id':52}];
The actual way is using JS Object.assign.
Object.assign(target, ...sources)
MDN Link
There is another object spread operator which is proposed for ES7 and can be used with Babel plugins.
Obj = {...sourceObj1, ...sourceObj2}
Use array reduce to create the new merged array of objects. Inside the callback function check if the accumulator array have an object which already have the code. For this use findIndex. If the code matches then update the error. Else push the current object in the accumulator
const data = [{"code":"12345","error":"12345 error 1"},{"code":"12345","error":"12345 error 2"},{"code":"67890","error":"67890 error 1"},{"code":"67890","error":"67890 error 2"},{"code":"67890","error":"67890 error 3"},{"code":"67890","error":"67890 error 4"},{"code":"67890","error":"67890 error 5"},{"code":"12092","error":"12092 error 1"},{"code":"12092","error":"12092 error 2"}];
let mergedData = data.reduce(function(acc, curr) {
let findIndex = acc.findIndex(function(item) {
return item.code === curr.code;
})
if (findIndex === -1) {
acc.push(curr)
} else {
acc[findIndex].error += ', ' + curr.error
}
return acc;
}, []);
console.log(mergedData)
Using Array#from, Array#reduce, Array#map and Map you could do somethign like this.
Idea is to first regroup everything with the Array#reduce and Map, and then to transform the data to the output you seek using Array#map.
const data = [{"code":"12345","error":"12345 error 1"},{"code":"12345","error":"12345 error 2"},{"code":"67890","error":"67890 error 1"},{"code":"67890","error":"67890 error 2"},{"code":"67890","error":"67890 error 3"},{"code":"67890","error":"67890 error 4"},{"code":"67890","error":"67890 error 5"},{"code":"12092","error":"12092 error 1"},{"code":"12092","error":"12092 error 2"}];
const res = Array.from(
data.reduce((a,{code, error})=>{
return a.set(code, [error].concat(a.get(code)||[]))
}, new Map())
).map(([code, error])=>({code, error: error.join(",")}));
console.log(res);
There are couple of different solutions to achieve this:
1 - Native javascript for-in loop:
const result = {};
let key;
for (key in obj1) {
if(obj1.hasOwnProperty(key)){
result[key] = obj1[key];
}
}
for (key in obj2) {
if(obj2.hasOwnProperty(key)){
result[key] = obj2[key];
}
}
2 - Object.keys():
const result = {};
Object.keys(obj1)
.forEach(key => result[key] = obj1[key]);
Object.keys(obj2)
.forEach(key => result[key] = obj2[key]);
3 - Object.assign():
(Browser compatibility: Chrome: 45, Firefox (Gecko): 34, Internet Explorer: No support, Edge: (Yes), Opera: 32, Safari: 9)
const result = Object.assign({}, obj1, obj2);
4 - Spread Operator:
Standardised from ECMAScript 2015 (6th Edition, ECMA-262):
Defined in several sections of the specification: Array Initializer, Argument Lists
Using this new syntax you could join/merge different objects into one object like this:
const result = {
...obj1,
...obj2,
};
5 - jQuery.extend(target, obj1, obj2):
Merge the contents of two or more objects together into the first object.
const target = {};
$.extend(target, obj1, obj2);
6 - jQuery.extend(true, target, obj1, obj2):
Run a deep merge of the contents of two or more objects together into the target. Passing false for the first argument is not supported.
const target = {};
$.extend(true, target, obj1, obj2);
7 - Lodash _.assignIn(object, [sources]): also named as _.extend:
const result = {};
_.assignIn(result, obj1, obj2);
8 - Lodash _.merge(object, [sources]):
const result = _.merge(obj1, obj2);
There are a couple of important differences between lodash's merge function and Object.assign:
1- Although they both receive any number of objects but lodash's merge apply a deep merge of those objects but Object.assign only merges the first level. For instance:
_.isEqual(_.merge({
x: {
y: { key1: 'value1' },
},
}, {
x: {
y: { key2: 'value2' },
},
}), {
x: {
y: {
key1: 'value1',
key2: 'value2',
},
},
}); // true
BUT:
const result = Object.assign({
x: {
y: { key1: 'value1' },
},
}, {
x: {
y: { key2: 'value2' },
},
});
_.isEqual(result, {
x: {
y: {
key1: 'value1',
key2: 'value2',
},
},
}); // false
// AND
_.isEqual(result, {
x: {
y: {
key2: 'value2',
},
},
}); // true
2- Another difference has to do with how Object.assign and _.merge interpret the undefined value:
_.isEqual(_.merge({x: 1}, {x: undefined}), { x: 1 }) // false
BUT:
_.isEqual(Object.assign({x: 1}, {x: undefined}), { x: undefined })// true
Update 1:
When using for in loop in JavaScript, we should be aware of our environment specially the possible prototype changes in the JavaScript types. For instance some of the older JavaScript libraries add new stuff to Array.prototype or even Object.prototype.
To safeguard your iterations over from the added stuff we could use object.hasOwnProperty(key) to mke sure the key is actually part of the object you are iterating over.
Update 2:
I updated my answer and added the solution number 4, which is a new JavaScript feature but not completely standardized yet. I am using it with Babeljs which is a compiler for writing next generation JavaScript.
Update 3:
I added the difference between Object.assign and _.merge.
WORKING FIDDLE
Simplest Way with Jquery -
var finalObj = $.extend(obj1, obj2);
Without Jquery -
var finalobj={};
for(var _obj in obj1) finalobj[_obj ]=obj1[_obj];
for(var _obj in obj2) finalobj[_obj ]=obj2[_obj];
You forgot to push obj in the first loop in case the id doesn't exist in c and to loop through c in case one or more id's of that object does not exist in g.
var g = [
{ id: 36, name: 'AAA', goal: 'yes' },
{ id: 40, name: 'BBB', goal: 'yes' },
{ id: 57, name: 'CCC', goal: 'yes' },
{ id: 4, name: 'DDD', goal: 'yes' },
{ id: 39, name: 'EEE', goal: 'yes' },
{ id: 37, name: 'FFF', goal: 'yes' },
{ id: 59, name: 'GGG', goal: 'yes' },
{ id: 50, name: 'III', goal: 'yes' },
{ id: 43, name: 'HHH', goal: 'yes' },
{ id: 35, name: 'JJJ', goal: 'yes' }
],
c = [
{ id: 36, name: 'AAA', circle: 'yes' },
{ id: 40, name: 'BBB', circle: 'yes' },
{ id: 57, name: 'CCC', circle: 'yes' },
{ id: 42, name: 'ZZZ', circle: 'yes' },
{ id: 4, name: 'DDD', circle: 'yes' },
{ id: 39, name: 'EEE', circle: 'yes' },
{ id: 37, name: 'FFF', circle: 'yes' },
{ id: 59, name: 'GGG', circle: 'yes' },
{ id: 43, name: 'HHH', circle: 'yes' },
{ id: 35, name: 'JJJ', circle: 'yes' },
{ id: 100, name: 'JJJ', circle: 'yes' }
],
arrayList = [], obj_c_processed = [];
for (var i in g) {
var obj = {id: g[i].id, name: g[i].name, goal: g[i].goal};
for (var j in c) {
if (g[i].id == c[j].id) {
obj.circle = c[j].circle;
obj_c_processed[c[j].id] = true;
}
}
obj.circle = obj.circle || 'no';
arrayList.push(obj);
}
for (var j in c){
if (typeof obj_c_processed[c[j].id] == 'undefined') {
arrayList.push({id: c[j].id, name: c[j].name, goal: 'no', circle: c[j].circle});
}
}
console.log(arrayList);
Using undescore.js, you can write some function like this:
var a = [ { id: 36, name: 'AAA', goal: 'yes' },
{ id: 40, name: 'BBB', goal: 'yes' },
{ id: 57, name: 'CCC', goal: 'yes' },
{ id: 4, name: 'DDD', goal: 'yes' },
{ id: 39, name: 'EEE', goal: 'yes' },
{ id: 37, name: 'FFF', goal: 'yes' },
{ id: 59, name: 'GGG', goal: 'yes' },
{ id: 50, name: 'III', goal: 'yes' },
{ id: 43, name: 'HHH', goal: 'yes' },
{ id: 35, name: 'JJJ', goal: 'yes' } ];
var b = [ { id: 36, name: 'AAA', circle: 'yes' },
{ id: 40, name: 'BBB', circle: 'yes' },
{ id: 57, name: 'CCC', circle: 'yes' },
{ id: 42, name: 'ZZZ', circle: 'yes' },
{ id: 4, name: 'DDD', circle: 'yes' },
{ id: 39, name: 'EEE', circle: 'yes' },
{ id: 37, name: 'FFF', circle: 'yes' },
{ id: 59, name: 'GGG', circle: 'yes' },
{ id: 43, name: 'HHH', circle: 'yes' },
{ id: 35, name: 'JJJ', circle: 'yes' },
{ id: 100, name: 'JJJ', circle: 'yes' } ];
function merge_object_arrays (arr1, arr2, match) {
return _.union(
_.map(arr1, function (obj1) {
var same = _.find(arr2, function (obj2) {
return obj1[match] === obj2[match];
});
return same ? _.extend(obj1, same) : obj1;
}),
_.reject(arr2, function (obj2) {
return _.find(arr1, function(obj1) {
return obj2[match] === obj1[match];
});
})
);
}
document.getElementsByTagName('pre')[0].innerHTML = JSON.stringify(
merge_object_arrays(a, b, 'id'), null, 2
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<pre>
</pre>
Try running it here.
You want the concat method.
var finalObj = json1.concat(json2);
Upon first appearance, the word "merg" leads one to think you need to use .extend, which is the proper jQuery way to "merge" JSON objects. However, $.extend(true, {}, json1, json2); will cause all values sharing the same key name to be overridden by the latest supplied in the params. As review of your question shows, this is undesired.
What you seek is a simple javascript function known as .concat. Which would work like:
var finalObj = json1.concat(json2);
While this is not a native jQuery function, you could easily add it to the jQuery library for simple future use as follows:
;(function($) {
if (!$.concat) {
$.extend({
concat: function() {
return Array.prototype.concat.apply([], arguments);
}
});
}
})(jQuery);
And then recall it as desired like:
var finalObj = $.concat(json1, json2);
You can also use it for multiple array objects of this type with a like:
var finalObj = $.concat(json1, json2, json3, json4, json5, ....);
And if you really want it jQuery style and very short and sweet (aka minified)
;(function(a){a.concat||a.extend({concat:function(){return Array.prototype.concat.apply([],arguments);}})})(jQuery);
;(function($){$.concat||$.extend({concat:function(){return Array.prototype.concat.apply([],arguments);}})})(jQuery);
$(function() {
var json1 = [{id:1, name: 'xxx'}],
json2 = [{id:2, name: 'xyz'}],
json3 = [{id:3, name: 'xyy'}],
json4 = [{id:4, name: 'xzy'}],
json5 = [{id:5, name: 'zxy'}];
console.log(Array(10).join('-')+'(json1, json2, json3)'+Array(10).join('-'));
console.log($.concat(json1, json2, json3));
console.log(Array(10).join('-')+'(json1, json2, json3, json4, json5)'+Array(10).join('-'));
console.log($.concat(json1, json2, json3, json4, json5));
console.log(Array(10).join('-')+'(json4, json1, json2, json5)'+Array(10).join('-'));
console.log($.concat(json4, json1, json2, json5));
});
center { padding: 3em; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<center>See Console Log</center>
jsFiddle
var json = '{"rows":[{"key":["zeit.de"],"value":98},{"key":["google.com"],"value":49},{"key":["spiegel.de"],"value":20},{"key":["spiegel.de"],"value":12},{"key":["spiegel.de"],"value":20},{"key":["spiegel.de"],"value":12},{"key":["netmng.com"],"value":49},{"key":["zeit.de"],"value":300}]}';
var obj = JSON.parse(json);
var newObj = {};
for(i in obj['rows']){
var item = obj['rows'][i];
if(newObj[item.key[0]] === undefined){
newObj[item.key[0]] = 0;
}
newObj[item.key[0]] += item.value;
}
var result = {};
result.rows = [];
for(i in newObj){
result.rows.push({'key':i,'value':newObj[i]});
}
console.log(result);
https://jsfiddle.net/s8rp84qc/
Here's an alternate solution using ECMA-Script Array functions forEach, some and filter:
var data = {
"rows": [{
"key": ["zeit.de"],
"value": 98
}, {
"key": ["google.com"],
"value": 49
}, {
"key": ["spiegel.de"],
"value": 20
}, {
"key": ["spiegel.de"],
"value": 12
}, {
"key": ["spiegel.de"],
"value": 20
}, {
"key": ["spiegel.de"],
"value": 12
}, {
"key": ["netmng.com"],
"value": 49
}, {
"key": ["zeit.de"],
"value": 300
}]
};
var merged = {
rows: []
};
data.rows.forEach(function(sourceRow) {
debugger;
if(!merged.rows.some(function(row) { return row.key[0] == sourceRow.key[0]; })) {
merged.rows.push({ key: [sourceRow.key[0]], value: sourceRow.value });
} else {
var targetRow = merged.rows.filter(function(targetRow) { return targetRow.key[0] == sourceRow.key[0] })[0];
targetRow.value += sourceRow.value;
}
});
document.getElementById("result").textContent = JSON.stringify(merged);
<div id="result"></div>