Reputation: 123
I need to merge JSON objects with same key into one so that it gets an object or array(doesn't matter if result is an object or array) which holds the key and an array for the values
example JSON object:
[{
"meine_frage": "hier kommt die antwort",
"ne_andere_frage": "ne andere antwort",
"was_willst_du": "alles",
"mehr_zur_auswahl": ["einiges", "vieles und", "g\u00e4r nix"]
}, {
"meine_frage": "tom & jerry",
"ne_andere_frage": "mickey maus",
"was_willst_du": "oder",
"mehr_zur_auswahl": ["manches", "einiges", "vieles und", "g\u00e4r nix"]
}, {
"meine_frage": "dick und doof",
"ne_andere_frage": "minnie muas",
"was_willst_du": "nichts",
"mehr_zur_auswahl": ["g\u00e4r nix"]
}]
result should look like:
[{
"meine_frage": ["hier kommt die antwort", "tom & jerry", "dick und doof"],
"ne_andere_frage": ["ne andere antwort", "mickey maus", "minnie muas"],
"was_willst_du": ["alles", "oder"],
"mehr_zur_auswahl": ["einiges", "vieles und", "g\u00e4r nix", "manches", "einiges", "vieles und", "g\u00e4r nix"]
}]
some values are already arrays whereas others not, the keys are genterated dynamically so assume the the key name is unkown
i tried iterating over the key/values with $.each and for loops but without success, also searched the web but couldnt find similar, appreciate any help
Upvotes: 10
Views: 17946
Reputation: 122027
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)
Upvotes: 13
Reputation: 150
The value gär nix
appears three times in your example JSON file but only twice in the desired output. I have assumed that you intend to merge all keys without considering redundancy in the values. Based on this assumption, here is the code for it:
function mergeJsonObjects(jsonArray) {
let mergedResult = {};
// Loop over each JSON object in the array
$.each(jsonArray, function (i, obj) {
// Loop over each key-value pair in the current JSON object
$.each(obj, function (key, value) {
// Check if the key exists in the merged result, if not, initialize it as an array
if (!mergedResult[key]) {
mergedResult[key] = [];
}
// If the value is already an array, merge it with the existing array
if (Array.isArray(value)) {
mergedResult[key] = mergedResult[key].concat(value);
} else {
// Otherwise, just add the value into the array
mergedResult[key].push(value);
}
});
});
return mergedResult;
}
// Your JSON Array
let jsonArray = [
{
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 maus",
was_willst_du: "nichts",
mehr_zur_auswahl: ["gär nix"],
},
];
let mergedJson = mergeJsonObjects(jsonArray);
console.log(JSON.stringify(mergedJson, null, 2));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
Upvotes: 0
Reputation: 18371
Using reduce and spread operator
var data = [{
"meine_frage": "hier kommt die antwort",
"ne_andere_frage": "ne andere antwort",
"was_willst_du": "alles",
"mehr_zur_auswahl": ["einiges", "vieles und", "g\u00e4r nix"]
}, {
"meine_frage": "tom & jerry",
"ne_andere_frage": "mickey maus",
"was_willst_du": "oder",
"mehr_zur_auswahl": ["manches", "einiges", "vieles und", "g\u00e4r nix"]
}, {
"meine_frage": "dick und doof",
"ne_andere_frage": "minnie muas",
"was_willst_du": "nichts",
"mehr_zur_auswahl": ["g\u00e4r nix"]
}]
let myData = data.reduce((b , a)=> {
Object.keys(a).forEach(key => {
if (Object.keys(b).indexOf(key) > -1) {
if (typeof a[key] === "object") {
b[key] = [...b[key], ...a[key]]
} else {
b[key].push(a[key])
}
} else {
if (typeof a[key] === "object") {
b[key] = [...a[key]]
} else {
b[key] = [a[key]]
}
}
})
return b
}, {})
console.log(myData)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 22524
You can use array#reduce
as a accumulator and iterate through each key of object and array#concat
the values.
var data = [{ "meine_frage": "hier kommt die antwort", "ne_andere_frage": "ne andere antwort", "was_willst_du": "alles", "mehr_zur_auswahl": ["einiges", "vieles und", "g\u00e4r nix"] }, { "meine_frage": "tom & jerry", "ne_andere_frage": "mickey maus", "was_willst_du":"oder", "mehr_zur_auswahl": ["manches", "einiges", "vieles und", "g\u00e4r nix"] }, { "meine_frage": "dick und doof", "ne_andere_frage": "minnie muas", "was_willst_du": "nichts", "mehr_zur_auswahl": ["g\u00e4r nix"] }];
var merged = data.reduce((r,o) => {
Object.keys(o).forEach(k => {
r[k] = (r[k] || []).concat(o[k]);
})
return r;
},{});
console.log(merged);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 48337
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]);
Upvotes: 5
Reputation: 1364
This function will do the work:
const example = array => {
let newObject = {}
array.forEach((element) => {
for(let key in element) {
if(typeof element[key] === 'object') {
element[key].forEach((el) => {
if(newObject[key] && newObject[key].length) {
newObject[key].push(el)
}
else {
newObject[key] = [el]
}
})
}
else {
if(newObject[key] && newObject[key].length){
newObject[key].push(element[key])
}
else{
newObject[key] = [element[key]]
}
}
}
})
return newObject
}
Upvotes: 3
Reputation: 1164
Use map
and check by Array.isArray
, try below code
var myArray = [{"meine_frage": "hier kommt die antwort","ne_andere_frage": "ne andere antwort","was_willst_du": "alles","mehr_zur_auswahl": ["einiges", "vieles und", "g\u00e4r nix"]}, {"meine_frage": "tom & jerry","ne_andere_frage": "mickey maus","was_willst_du": "oder","mehr_zur_auswahl": ["manches", "einiges", "vieles und", "g\u00e4r nix"]}, {"meine_frage": "dick und doof","ne_andere_frage": "minnie muas","was_willst_du": "nichts","mehr_zur_auswahl": ["g\u00e4r nix"]}];
var findKeyOf = function(key){
var temp = myArray.map(function(e){
return e[key];
});
var test = [];
for(let i in temp){
if(Array.isArray(temp[i]) ){
test = test.concat(temp[i]);
}else{
test.push(temp[i])
}
}
return test;
};
var newArr = [
{meine_frage:findKeyOf('meine_frage')},
{ne_andere_frage:findKeyOf('ne_andere_frage')},
{was_willst_du:findKeyOf('was_willst_du')},
{mehr_zur_auswahl:findKeyOf('mehr_zur_auswahl')},
]
console.log(newArr);
Upvotes: 2