santosh
santosh

Reputation: 190

Get list of duplicate objects in an array based on two property in javascript

I am trying to get duplicate objects within an array based on 2 properties. Let's say the object is like below.

let arry = [
    {Level: "A-1", Status: "approved"},
    {Level: "A-2", Status: "approved"},
    {Level: "A-3", Status: "approved"},
    {Level: "A-4", Status: "reject"},
    {Level: "A-5", Status: "reject"},
    {Level: "A-1", Status: "approved"},
    {Level: "A-2", Status: "approved"},
    {Level: "A-6", Status: "approved"},
    {Level: "A-7", Status: "reject"},
    {Level: "A-1", Status: "approved"},
    {Level: "A-6", Status: "approved"},
]

Duplicate objects should return and only the Status "approved" once like below:

[
{Level: "A-1", Status: "approved"},
 {Level: "A-2", Status: "approved"}
]

Upvotes: 0

Views: 696

Answers (2)

Gorynych
Gorynych

Reputation: 100

let arry = [
    {Level: "A-1", Status: "approved"},
    {Level: "A-2", Status: "approved"},
    {Level: "A-3", Status: "approved"},
    {Level: "A-4", Status: "reject"},
    {Level: "A-5", Status: "reject"},
    {Level: "A-1", Status: "approved"},
    {Level: "A-2", Status: "approved"},
    {Level: "A-6", Status: "approved"},
    {Level: "A-7", Status: "reject"},
    {Level: "A-1", Status: "approved"},
    {Level: "A-6", Status: "approved"},
]

function dups(arry) {
  const hashMap = {};

  return arry.reduce((acc, curr) => {
    const level = curr.Level;
    if(hashMap[level] && hashMap[level] === 1 && curr.Status === 'approved') {
      acc.push(curr);
      hashMap[level]++;
    } else {
      hashMap[level] = 1;
    }

    return acc;
  }, []);
}

console.log(dups(arry));

Upvotes: 1

GirkovArpa
GirkovArpa

Reputation: 4912

You can use Array.reduce to keep track of all the previous items as it iterates through the array, while preserving only the ones it's seen before (whose Status is "approved").

In order to not output duplicates of duplicates, it also checks if the current duplicate was already found as a duplicate, and ignores it if so.

const array = [
  { Level: "A-1", Status: "approved" },
  { Level: "A-2", Status: "approved" },
  { Level: "A-3", Status: "approved" },
  { Level: "A-4", Status: "reject" },
  { Level: "A-5", Status: "reject" },
  { Level: "A-1", Status: "approved" },
  { Level: "A-2", Status: "approved" },
  { Level: "A-6", Status: "approved" },
  { Level: "A-7", Status: "reject" },
  { Level: "A-1", Status: "approved" },
  { Level: "A-6", Status: "approved" },
];

const dupes = array.reduce((dupes, { Level, Status }, i) => {
  const matches = ({ Level: l, Status: s }) => l == Level && s == Status;
  const match = dupes.memory.find(matches);
  const found = dupes.dupes.find(matches);
  (match?.Status == 'approved' && !found)
    ? dupes.dupes.push({ Level, Status })
    : dupes.memory.push({ Level, Status });
  return (i == array.length - 1) ? dupes.dupes : dupes;
}, { dupes: [], memory: [] });

console.log(dupes);

A less general but more terse strategy might be:

const dupes = [...new Set(array
  .filter(({ Status: s }) => s == 'approved')
  .map(({ Level: l }) => +l.match(/\d+/)[0])
  .filter((num, _, arr) => arr.filter((n) => n == num).length > 1))]
  .map((n) => ({ Level: 'A-' + n, Status: 'approved' }));

For example:

const array = [
  { Level: "A-1", Status: "approved" },
  { Level: "A-2", Status: "approved" },
  { Level: "A-3", Status: "approved" },
  { Level: "A-4", Status: "reject" },
  { Level: "A-5", Status: "reject" },
  { Level: "A-1", Status: "approved" },
  { Level: "A-2", Status: "approved" },
  { Level: "A-6", Status: "approved" },
  { Level: "A-7", Status: "reject" },
  { Level: "A-1", Status: "approved" },
  { Level: "A-6", Status: "approved" },
];

const dupes = [...new Set(array
  .filter(({ Status: s }) => s == 'approved')
  .map(({ Level: l }) => +l.match(/\d+/)[0])
  .filter((num, _, arr) => arr.filter((n) => n == num).length > 1))]
  .map((n) => ({ Level: 'A-' + n, Status: 'approved' }));

console.log(dupes);

Upvotes: 1

Related Questions