10

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

2
  • 6
    where is your js code? Commented Dec 21, 2017 at 11:24
  • thank you all for your quick answers Commented Dec 21, 2017 at 12:49

7 Answers 7

13

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)

Sign up to request clarification or add additional context in comments.

1 Comment

This is good and quite close to being functional. With a few tweaks you could make it so: replace the if/else and assignments with a ternary return statement, and use that function in array_map_associative.
5

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

Comments

3

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
}

Comments

2

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

Comments

2

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

Comments

2

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

2 Comments

Where did you used destructing assignment ?
@MihaiAlexandru-Ionut, I updated my answer. It is the spread operator
0

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.