Rusty23
Rusty23

Reputation: 71

Join objects with one same property within different arrays

I have this array, that contains more arrays with objects inside that contains information about words founded in pages. Here one example:

let data = [
  [],
  [{
      "word": "society",
      "count": 5,
      "pageIndex": 1
    },
    {
      "word": "identity",
      "count": 2,
      "pageIndex": 1
    }
  ],
  [{
      "word": "society",
      "count": 2,
      "pageIndex": 2
    },
    {
      "word": "identity",
      "count": 2,
      "pageIndex": 2
    }
  ],
  [{
      "word": "society",
      "count": 2,
      "pageIndex": 3
    },
    {
      "word": "identity",
      "count": 1,
      "pageIndex": 3
    }
  ],
  [],
  [],
  [{
    "word": "society",
    "count": 1,
    "pageIndex": 6
  }],
  [],
  [{
    "word": "society",
    "count": 1,
    "pageIndex": 8
  }],
  [{
    "word": "society",
    "count": 1,
    "pageIndex": 9
  }]
]

What I want is to build a final array of objects with this structure to join the information of each word founded in just one object

const final = [{
    "word": "society",
    "countFinal": 12,
    "pagesIndexes": [1, 2, 3, 6, 8, 9]
  },
  {
    "word": "identity",
    "countFinal": 5,
    "pagesIndexes": [1, 2, 3]
  }
]

Any ideas on how to achieve this in JS?

Upvotes: 1

Views: 87

Answers (3)

Nick Parsons
Nick Parsons

Reputation: 50684

One way could be to use a Map with .reduce(). The map would store keys which are the words from each object, along with its values being the modified objects with arrays for the pagesIndexes value. Whenever you come across a word that is already a key in the map, you can add to its pagesIndexes array. If you encounter a new word that isn't in the map, you can start a new array of its associated object which contains the current objects pageIndex. You can then grab the values from your Map using .values() and Array.from() to convert the value iterator into an array.

See example below

const data = [[], [{ "word": "society", "count": 5, "pageIndex": 1 }, { "word": "identity", "count": 2, "pageIndex": 1 } ], [{ "word": "society", "count": 2, "pageIndex": 2 }, { "word": "identity", "count": 2, "pageIndex": 2 } ], [{ "word": "society", "count": 2, "pageIndex": 3 }, { "word": "identity", "count": 1, "pageIndex": 3 } ], [], [], [{ "word": "society", "count": 1, "pageIndex": 6 }], [], [{ "word": "society", "count": 1, "pageIndex": 8}], [{ "word": "society", "count": 1, "pageIndex": 9 }] ];

const res = Array.from(data.reduce((acc, arr) => {
  return new Map([...acc, ...arr.map(c => {
    const o = acc.get(c.word);
    return [c.word, {...o, ...c, pagesIndexes: [...(o && o.pagesIndexes || []), c.pageIndex]}];
  })]);
}, new Map).values());

console.log(res);

Upvotes: 1

MohammadReza Abbasi
MohammadReza Abbasi

Reputation: 500

var data = [
  [],
  [{
    "word": "society",
    "count": 5,
    "pageIndex": 1
  }, {
    "word": "identity",
    "count": 2,
    "pageIndex": 1
  }],
  [{
    "word": "society",
    "count": 2,
    "pageIndex": 2
  }, {
    "word": "identity",
    "count": 2,
    "pageIndex": 2
  }],
  [{
    "word": "society",
    "count": 2,
    "pageIndex": 3
  }, {
    "word": "identity",
    "count": 1,
    "pageIndex": 3
  }],
  [],
  [],
  [{
    "word": "society",
    "count": 1,
    "pageIndex": 6
  }],
  [],
  [{
    "word": "society",
    "count": 1,
    "pageIndex": 8
  }],
  [{
    "word": "society",
    "count": 1,
    "pageIndex": 9
  }]
];

let end_obj = {}
data.forEach(element => {
  element.forEach(sub => {
    if (!end_obj[sub.word]) {
      end_obj[sub.word] = {
        word: sub.word,
        countFinal: 0,
        pagesIndexes: []
      }
    }
    end_obj[sub.word].countFinal += sub.count
    end_obj[sub.word].pagesIndexes.push(sub.pageIndex)
  });
});

let end_arr = []
for (const key in end_obj) {
  const element = end_obj[key];
  end_arr.push(element)
}

console.log(end_arr);

Upvotes: 1

Rajneesh
Rajneesh

Reputation: 5308

You will first flat the data, afterward you can reduce (in order to group data based on word property). Once reduced, you can take Object.values of the object. Here is an implementation:

var data = [ [], [{ "word": "society", "count": 5, "pageIndex": 1 }, { "word": "identity", "count": 2, "pageIndex": 1 } ], [{ "word": "society", "count": 2, "pageIndex": 2 }, { "word": "identity", "count": 2, "pageIndex": 2 } ], [{ "word": "society", "count": 2, "pageIndex": 3 }, { "word": "identity", "count": 1, "pageIndex": 3 } ], [], [], [{ "word": "society", "count": 1, "pageIndex": 6 }], [], [{ "word": "society", "count": 1, "pageIndex": 8 }], [{ "word": "society", "count": 1, "pageIndex": 9 }]];

var result = Object.values(data.flat().reduce((a,{word, count, pageIndex})=>{
    a[word] = a[word] || {word, countFinal:0, pageIndexes:[]};
    a[word].countFinal+=count;
    a[word].pageIndexes.push(pageIndex);
    return a;
},{}));

console.log(result);

Upvotes: 3

Related Questions