将具有相同键的 JSON 对象合并在一起

Posted

技术标签:

【中文标题】将具有相同键的 JSON 对象合并在一起【英文标题】:Merging JSON objects with same key together 【发布时间】:2018-06-04 01:29:02 【问题描述】:

我需要将具有相同键的 JSON 对象合并为一个对象或数组(不管结果是对象还是数组),其中包含键和值的数组

示例 JSON 对象:

[
    "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"]

]

结果应该是这样的:

[
    "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"]
]

有些值已经是数组,而有些不是,键是动态生成的,所以假设键名是未知的

我尝试使用 $.each 和 for 循环迭代键/值,但没有成功,还搜索了网络,但找不到类似的, 感谢任何帮助

【问题讨论】:

你的js代码在哪里? 感谢大家的快速解答 【参考方案1】:

您可以为此使用reduce()concat() 方法。

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"]]

const result = data.reduce(function(r, e) 
  return Object.keys(e).forEach(function(k) 
    if(!r[k]) r[k] = [].concat(e[k])
    else r[k] = r[k].concat(e[k])
  ), r
, )

console.log(result)

【讨论】:

这很好,非常接近实用。通过一些调整,您可以做到这一点:用三元 return 语句替换 if/else 和赋值,并在 array_map_associative 中使用该函数。【参考方案2】:

您可以通过将callback 函数作为参数传递来使用reduce 方法。

算法如下:如果最终对象已经包含一个键,那么您应该用一个空的数组初始化该键的值。否则,您应该追加数组中所有项目的数组值。

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

【讨论】:

【参考方案3】:

这个函数可以完成工作:

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

【讨论】:

【参考方案4】:

使用mapArray.isArray检查,试试下面的代码

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

【讨论】:

【参考方案5】:

您可以使用array#reduce 作为累加器并遍历对象的每个键和array#concat 的值。

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; 

【讨论】:

【参考方案6】:

使用reduce 和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; 

【讨论】:

你在哪里使用了破坏赋值? @MihaiAlexandru-Ionut,我更新了我的答案。这是spread operator

以上是关于将具有相同键的 JSON 对象合并在一起的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法合并两个具有相同键的 JS 对象? [复制]

合并 2 个具有相同键的对象,来自 2 个数组的值

合并具有相同属性值的json对象c#

如何解析具有相同键的不同数据类型的改造对象的json数组

使用角度js将具有相同ID的重复对象从json数据合并为单个对象

将字符串转换为具有重复键的对象到数组