-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.

4
  • 1
    do you have some not optimal code? Commented Sep 25, 2020 at 7:51
  • What defines if an entry is a duplicate? The id? The value? Or id and value? Commented Sep 25, 2020 at 7:51
  • @ChristianBaumann just the value. Commented Sep 25, 2020 at 7:53
  • Please visit the help center, take the tour to see what and How to Ask. Do some research, search for related topics on SO; if you get stuck, post a minimal reproducible example of your attempt, noting input and expected output using the [<>] snippet editor. Commented Sep 25, 2020 at 7:55

6 Answers 6

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);

Sign up to request clarification or add additional context in comments.

2 Comments

@b9s - Yes, it does -- note the previous part where it marks duplicates. :-) That's why it's a Map and not just a Set.
@b9s click on "Show code snippet" to check the runnable snippet.
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;
    }
});

2 Comments

Could use counter[item.value] = (counter[item.value] || 0) + 1 to simplify the conditional.
There's no need for two passes through the array to do this. (But this is still a viable approach.)
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)

Comments

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.

Comments

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.

Comments

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; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.