Search code examples
javascriptarraysobjectlodashjavascript-objects

How do I combine a list of objects where each object has duplicate category and unique article?


I would like to combine all the article objects in this dataset:

const data = [
  {
    category: {
      id: 1,
    },
    article: {
      title: 'aaa',
    },
  },
  {
    category: {
      id: 1,
    },
    article: {
      title: 'bbb',
    },
  },
  {
    category: {
      id: 2,
    },
    article: {
      title: 'ccc',
    },
  },
  {
    category: {
      id: 3,
    },
    article: {
      title: 'ddd',
    },
  },
  {
    category: {
      id: 3,
    },
    article: {
      title: 'eee',
    },
  },
]

Underneath the same category if the category.id matches. Like so:

[
  {
    category: {
      id: 1,
    },
    articles: [
      {
        title: 'aaa',
      },
      {
        title: 'bbb',
      },
    ]
  },
  {
    category: {
      id: 2,
    },
    articles: [
      {
        title: 'ccc',
      }
    ],
  },
  {
    category: {
      id: 3,
    },
    articles: [
      {
        title: 'ddd',
      },
      {
        title: 'eee'
      }
    ]
  },
]

Any ideas? Happy to use Lodash something. Thank you!


Solution

  • You can use reduce function. Inside reduce call back function use findIndex to check if the accumulator array have an object with id same as id of the current object under iteration. If it is same then update the articles array else create a new object with required key and push it to the accumulator array

    const data = [{
        category: {
          id: 1,
        },
        article: {
          title: 'aaa',
        },
      },
      {
        category: {
          id: 1,
        },
        article: {
          title: 'bbb',
        },
      },
      {
        category: {
          id: 2,
        },
        article: {
          title: 'ccc',
        },
      },
      {
        category: {
          id: 3,
        },
        article: {
          title: 'ddd',
        },
      },
      {
        category: {
          id: 3,
        },
        article: {
          title: 'eee',
        },
      }
    ]
    
    
    let newData = data.reduce(function(acc, curr) {
      let findIdIndex = acc.findIndex(function(item) {
        return item.category.id === curr.category.id
      });
    
      if (findIdIndex === -1) {
        acc.push({
          category: {
            id: curr['category']['id']
          },
          articles: [{
            title: curr.article.title
          }]
        })
    
    
      } else {
        acc[findIdIndex].articles.push({
          title: curr.article.title
        })
    
      }
      return acc;
    }, []);
    
    console.log(newData)