如何将具有相同属性的对象合并为一个数组?

4
我正在接收下一个数据。
    [
      { id: "1", name: "test1", rName: "the1" },
      { id: "1", name: "test1", rName: "the2" },
      { id: "1", name: "test1", rName: "the3" },
      { id: "2", name: "test2", rName: "the1" },
      { id: "2", name: "test2", rName: "the2" },
      { id: "3", name: "test3", rName: "the1" }
    ]

我希望通过id合并它,并将rName推入一个数组中,以获得这种结构。
    [
      { id: "1", name: "test1", rName: ["the1", "the2","the3"] },
      { id: "2", name: "test2", rName: ["the1", "the2"] },
      { id: "3", name: "test3", rName: ["the1"] }
    ]

我曾尝试使用reduce方法,但未能成功,如果有人能指导我正确的方向,将不胜感激。


1
请添加您的内容: - Nina Scholz
5个回答

2
这是一个相当简单的数据重新格式化示例。以下是代码。

var data = [
  { id: "1", name: "test1", rName: "the1" },
  { id: "1", name: "test1", rName: "the2" },
  { id: "1", name: "test1", rName: "the3" },
  { id: "2", name: "test2", rName: "the1" },
  { id: "2", name: "test2", rName: "the2" },
  { id: "3", name: "test3", rName: "the1" }
];
    
var reduced = Object.values(data.reduce(function(accumulator, element) {
  if (!accumulator[element.id]) {
    accumulator[element.id] = { id: element.id, name: element.name, rName: [] };
  }
  
  accumulator[element.id].rName.push(element.rName);
  return accumulator;
}, {}));
console.log(reduced);

累加器通过element.id检查累加器中是否存在键。如果不存在,则创建一个新的键。然后将新的rName推送到现有堆栈上。接着使用Object.values()将其转换回数组。


1
你可以这样使用 reducefind
在reduce的accumulator中,检查是否已经有一个与正在迭代的当前项具有相同id的项。如果是,则将当前项的rName推入rName数组。否则,将一个新项推入accumulator

var data = [
      { id: "1", name: "test1", rName: "the1" },
      { id: "1", name: "test1", rName: "the2" },
      { id: "1", name: "test1", rName: "the3" },
      { id: "2", name: "test2", rName: "the1" },
      { id: "2", name: "test2", rName: "the2" },
      { id: "3", name: "test3", rName: "the1" }
      ];

const newArray = data.reduce((acc, {id,name,rName}) => {
    const existing = acc.find(a => a.id == id);
    if (existing)
        existing["rName"].push(rName);
    else
        acc.push({id,name,rName: [rName]})
    return acc
}, []);

console.log(newArray)

这是一行代码高尔夫答案。(灵感来自@Sébastien的答案):

var data = [
  { id: "1", name: "test1", rName: "the1" },
  { id: "1", name: "test2", rName: "the2" },
  { id: "1", name: "test2", rName: "the3" },
  { id: "2", name: "test2", rName: "the1" },
  { id: "2", name: "test1", rName: "the2" },
  { id: "3", name: "test3", rName: "the1" }
]

const anotherArray = Object.values(data.reduce((acc, {id,name,rName}) =>
      ((acc[id] = acc[id] || {id,name,rName:[]})["rName"].push(rName), acc), {}));

console.log(anotherArray)


我喜欢你的回答,谢谢你的解释。你认为除了reduce之外还有更好的方法吗? - Dangur
不确定您所说的“更好的方法”是什么意思。如果您不想使用reduce,您可以通过在外部声明一个acc数组并执行与reduce中所做的相同逻辑来使用forEach实现相同的功能。 - adiga

0

纯ES6

let result = obj.reduce((acc, item) => {
  let found = acc.find(i => i.id === item.id);
  found ? (found.rName = [...found.rName, item.rName]) : (acc = [...acc, { ...item, rName: [item.rName] }]);
  return acc;
}, []);

0
如果每个id可以确定一个唯一的name,那么这将起作用:
let data = [
  { id: "1", name: "test1", rName: "the1" },
  { id: "1", name: "test1", rName: "the2" },
  { id: "1", name: "test1", rName: "the3" },
  { id: "2", name: "test2", rName: "the1" },
  { id: "2", name: "test2", rName: "the2" },
  { id: "3", name: "test3", rName: "the1" }
];

let result = [];

for (let item of data) 
{
    const index = result.findIndex(i => i.id === item.id);
    if (index < 0) {
        result.push({ id: item.id, name: item.name, rName: [item.rName] });
    }
    else {
        result[index].rName.push(item.rName);
    }
}

请注意,当下列数据应被接受时,此方法将不起作用:
[
  { id: "1", name: "test1", rName: "the1" },
  { id: "1", name: "test2", rName: "the2" },
  { id: "1", name: "test2", rName: "the3" },
  { id: "2", name: "test2", rName: "the1" },
  { id: "2", name: "test1", rName: "the2" },
  { id: "3", name: "test3", rName: "the1" }
]

0
如果您坚持使用'reduce'方法,可以这样做:
var arr = [
        { id: "1", name: "test1", rName: "the1" },
        { id: "1", name: "test1", rName: "the2" },
        { id: "1", name: "test1", rName: "the3" },
        { id: "2", name: "test2", rName: "the1" },
        { id: "2", name: "test2", rName: "the2" },
        { id: "3", name: "test3", rName: "the1" }
    ]
    var arr1 = arr.reduce(function (a1, a2) {
        if (a1 instanceof Array) {
            let lastItem = a1[a1.length - 1]
            if (lastItem.id == a2.id) {
                lastItem.rName.push(a2.rName)
            } else {
                a1.push({ ...a2, rName: [a2.rName] })
            }
            return a1
        } else {
            let result = []
            if (a1.id == a2.id) {
                result.push({ ...a1, rName: [a1.rName, a2.rName] })
            } else {
                result.push({ ...a1, rName: [a1, rName] })
                result.push({ ...a2, rName: [a2, rName] })
            }
            return result

        }

    })
    console.log(JSON.stringify(arr1))

但我认为你应该这样做,因为代码更清晰:

var arr = [
    { id: "1", name: "test1", rName: "the1" },
    { id: "1", name: "test1", rName: "the2" },
    { id: "1", name: "test1", rName: "the3" },
    { id: "2", name: "test2", rName: "the1" },
    { id: "2", name: "test2", rName: "the2" },
    { id: "3", name: "test3", rName: "the1" }
]
var map = new Map()
arr.forEach(function(item){
    if(map.has(item.id)){
        map.get(item.id).rName.push(item.rName)
    }else{
        map.set(item.id, {...item, rName: [item.rName]})
    }
})
var arr1 = Array.from(map.values())
console.log(JSON.stringify(arr1))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接