简体   繁体   中英

Combine array of objects inner array based on property

say I have a data structure that looks like this:

data = [
        {title: "Alpha", content: [{ // 1 item }]},
        {title: "Beta", content: [{ // 10 items }]},
        {title: "Beta", content: [{ // 12 items }]}, 
        {title: "Beta", content: [{ // 8 items }]} 
       ]

I'd like to figure out a reduce function that would return the following structure:

data = [
        {title: "Alpha", content: [{ // 1 item }]},
        {title: "Beta", content: [{ // 30 items }]}
       ]

I've tried looking at some answers where reduce is used based on title but it did not return the new structure with the accumulated content array such as:

data = data.reduce((x, e) => {
          x.push(
            Object.assign(
              {},
              e,
              messages.find((x) => x.title == e.title)
            )
          )
          return x
        }, [])

Any help would be great.

This might help -

 var data = [{ title: "Alpha", content: [1, 2, 3, 4, 5] }, { title: "Beta", content: [6, 7, 8, 9, 10] }, { title: "Beta", content: [11, 12, 13, 14, 15] }, { title: "Beta", content: [16, 17, 18, 19, 20] } ] data = data.reduce((array, item) => { const existingItem = array.find(innerItem => innerItem.title === item.title); if (..existingItem) { existingItem.content = [..,existingItem.content. ..;item.content]; } else { array;push(item), } return array; }. []); console.log(data);

You don't need to use .find , which has to search the entire array every iteration.

Using reduce and an object map to collect dupes, Object.values to unwrap object to array. spread syntax to feed as push arguments.

 data = [ {title: "Alpha", content: [{ 1:1 }]}, {title: "Beta", content: [{2:2 }]}, {title: "Beta", content: [{ 3:3}]}, {title: "Beta", content: [{4:4}] } ] console.log( Object.values(data.reduce((acc,{title,content})=>{ acc[title]? acc[title].content.push(...content): acc[title] = { title, content } return acc },{}) ))

If IE compatible is needed, there is a polyfill on the above linked documentation. This will also work:

 data = [ {title: "Alpha", content: [{ 1:1 }]}, {title: "Beta", content: [{2:2 }]}, {title: "Beta", content: [{ 3:3}]}, {title: "Beta", content: [{4:4}] } ] function values(obj){ return Object.keys(obj).map(k=>obj[k]) } console.log( values(data.reduce((acc,x)=>{ acc[x.title] = acc[x.title] || {title: x.title, content: []} acc[x.title].content = acc[x.title].content.concat(x.content) return acc },{}) ))

I made small changes from @user120242 code.

 data = [ {title: "Alpha", content: [{ 1:1 }]}, {title: "Beta", content: [{2:2 }]}, {title: "Beta", content: [{ 3:3}]}, {title: "Beta", content: [{4:4}] } ] let acc={}; data.forEach((x)=>{ acc[x.title] = acc[x.title] || {title: x.title, content: []} acc[x.title].content = acc[x.title].content.concat(x.content) } ) console.log(acc)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM