-1

The question might be a bit vague, but I'll explain the result I'm expecting to get with an example.

Say I have the following array made out of objects with the following shape:

[
   {
      id: 1,
      value: 10
   },
   {
      id: 2,
      value: 100
   },
   {
      id: 3,
      value: 10
   },
   {
      id: 4,
      value: 10
   },
   {
      id: 5,
      value: 1000
   },

]

This array might contain hundrends, maybe thousands of entries, but for simplicity, I'll keep it small.

What I'm trying to achieve is compare the value property of every object with the other value properties and assign a new property duplicate with a boolean value to that specific object.

Given the example above, I would expect to receive an array with the following members:

[
  {
     id: 1,
     value: 10,
     duplicate: true
  },
  {
     id: 2,
     value: 100
  },
  {
     id: 3,
     value: 10,
     duplicate: true
  },
  {
     id: 4,
     value: 10,
     duplicate: true
  },
  {
     id: 5,
     value: 1000
  },

]

Whats the most optimal way I could implement this behavior ?

Thank you.

As above so below
  • 619
  • 1
  • 6
  • 13

6 Answers6

5

I'd do a single pass through the array remembering the first seen entry with a given value in a Map, marking that first entry (and any others) as duplicates if it's present, like this:

const map = new Map();
for (const entry of array) {
    const previous = map.get(entry.value);
    if (previous) {
        previous.duplicate = entry.duplicate = true;
    } else {
        map.set(entry.value, entry);
    }
}

Live Example:

const array = [
   {
      id: 1,
      value: 10
   },
   {
      id: 2,
      value: 100
   },
   {
      id: 3,
      value: 10
   },
   {
      id: 4,
      value: 10
   },
   {
      id: 5,
      value: 1000
   },

];

const map = new Map();
for (const entry of array) {
    const previous = map.get(entry.value);
    if (previous) {
        previous.duplicate = entry.duplicate = true;
    } else {
        map.set(entry.value, entry);
    }
}

console.log(array);
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

You can do this by first determining which are the duplicates, and then setting the 'duplicate' attribute.

counts = items.reduce((counter, item) => {
    if (counter[item.value] != null) {
        counter[item.value] += 1;
    } else {
        counter[item.value] = 1;
    }
    return counter;
}, {});

After this, you can go over your items, and if the count is >=2, set the 'duplicate' attribute.

items.forEach((item) => {
    if (counter[item.value] > 1) {
        item['duplicate'] = true;
    }
});
b9s
  • 517
  • 4
  • 13
1

You can use Array.map and Array.filter for that.

const input = [
  { id: 1, value: 10 },
  { id: 2, value: 100 },
  { id: 3, value: 10 },
  { id: 4, value: 10 },
  { id: 5, value: 1000 }
]

const output = input.map(entry => {
  if (input.filter(x => x.value === entry.value).length > 1) {
    return {
      duplicate: true,
      ...entry
    }
  }
  
  return entry
})

console.log(output)
Magiczne
  • 1,586
  • 2
  • 15
  • 23
0

A copy from myself with a single loop and an object for storing seen values.

This approach returns a new array and does not mutate the given data.

var data = [{ id: 1, value: 10 }, { id: 2, value: 100 }, { id: 3, value: 10 }, { id: 4, value: 10 }, { id: 5, value: 1000 }],
    result = data.map((seen => ({ ...o }) => {
        if (o.value in seen) {
            o.duplicate = true;
            if (seen[o.value]) {
                seen[o.value].duplicate = true;
                seen[o.value] = false;
            }
        } else seen[o.value] = o;
        return o;
    })({}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

I would create a map with value as the key, and a list of ids as the values, than after iterating over the whole map and creating the new mapping, unpack it back tothe desired form, and add duplicated for keys with more than one value.

Uriya Harpeness
  • 628
  • 1
  • 6
  • 21
0

I think this will help you. arr is your array.

arr.forEach(e=> {
  const dublicatedDataLenth = arr.filter(a => a.value == e.value).length;
  if(dublicatedDataLenth > 1){
    e.dublicate = true;
  }
})

It should be what you are looking for.

Hasip Timurtas
  • 983
  • 2
  • 11
  • 20