合并具有相同JSON键的对象

时间:2019-03-06 14:43:38

标签: javascript arrays json

我在通过键将JSON对象数组合并在一起时遇到了一些麻烦。有人会只使用Javascript有一个好的解决方案吗?

{
    "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"
}

应转换为

{
    "code": "12345",
    "error": "12345 error 1, 12345 error 2"
},
{
    "code": "67890",
    "error": "67890 error 1, 67890 error 2, 67890 error 3, 67890 error 4, 67890 error 5"
},
{
    "code": "12092",
    "error": "12092 error 1, 12092 error 2"
}

任何帮助将不胜感激。我已经为此花费了很长时间,但似乎无法克服它。

3 个答案:

答案 0 :(得分:4)

使用数组reduce创建对象的新合并数组。在回调函数内部,检查累加器数组是否具有已经具有code的对象。为此使用findIndex。如果代码匹配,则更新error。否则将当前对象推入累加器

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)

答案 1 :(得分:1)

使用Array#fromArray#reduceArray#mapMap,您可以做这样的事情。

想法是首先使用Array#reduce和Map重新组合所有内容,然后将数据转换为使用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);

答案 2 :(得分:1)

使用Reduce并检查现有对象键的现有答案是完美的。

这是使用Map和其他ES6语法(for...of)来完成此操作的另一种方法,我认为这很容易理解,并且是另一种有趣的方法:

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

// Define a new empty Map.
const map = new Map();

// Loop through all data objects.
for (const dataEntry of data) {

  // Check if we've already added this to our map; if not, add blank entry.
  if (!map.has(dataEntry.code)) {
      map.set(dataEntry.code, {code: dataEntry.code,error:[]});
  }

  // Append to the error property.
  const mapEntry = map.get(dataEntry.code);
  mapEntry.error.push(dataEntry.error);

}

// Flatten the error entries to be a single String instead of an Array.
for (const entry of map.values()) {
  entry.error = entry.error.join(', ');
}

const output = Array.from(map.values());

console.log(output);