Search code examples
javascriptarraysmergemapreducelodash

Merging multiple JSON objects from an array together


I have an array of JSON objects and I want to merge the objects that have the same text together while finding the average of relevance and the sum of count across all of the same instances.


var keywords = [
            {
                "text": "service businesses",
                "relevance": 0.626303,
                "count": 1
            },
            {
                "text": "service businesses",
                "relevance": 0.87319,
                "count": 5
            },
            {
                "text": "service businesses",
                "relevance": 0.05,
                "count": 100
            },
            {
                "text": "restaurants",
                "relevance": 0.614567,
                "count": 16
            },
            {
                "text": "restaurants",
                "relevance": 0.609875,
                "count": 4
            },
            {
                "text": "hotels",
                "relevance": 0.594905,
                "count": 1
            },

I tried the solution posted here but, I am getting an output like this:

{
    text: 'service businesses',
    count: '[object Object][object Object]'
  }

The output I am hoping for would look like this:

            {
                "text": "service businesses",
                "relevance": 0.516497667,
                "count": 106
            },

            {
                "text": "restaurants",
                "relevance": 0.612221,
                "count": 20
            },
            {
                "text": "hotels",
                "relevance": 0.594905,
                "count": 1
            },

Any help is much appreciated!


Solution

  • Using Array.prototype.reduce, you can group the elements by the text and based on that group data, can get the output as follows.

    var keywords = [{
        "text": "service businesses",
        "relevance": 0.626303,
        "count": 1
      },
      {
        "text": "service businesses",
        "relevance": 0.87319,
        "count": 5
      },
      {
        "text": "service businesses",
        "relevance": 0.05,
        "count": 100
      },
      {
        "text": "restaurants",
        "relevance": 0.614567,
        "count": 16
      },
      {
        "text": "restaurants",
        "relevance": 0.609875,
        "count": 4
      },
      {
        "text": "hotels",
        "relevance": 0.594905,
        "count": 1
      }
    ];
    
    const groupBy = keywords.reduce((acc, cur) => {
      acc[cur.text] ? acc[cur.text] = {
        ...acc[cur.text],
        count: acc[cur.text].count + cur.count,
        relevance: [...acc[cur.text].relevance, cur.relevance]
      } : acc[cur.text] = {
        ...cur,
        relevance: [cur.relevance]
      };
      return acc;
    }, {});
    const output = Object.values(groupBy).map((item) => ({
      ...item,
      relevance: item.relevance.reduce((acc, cur) => acc + cur, 0) / item.relevance.length
    }));
    console.log(output);