2

How can I check for possible duplicates in an array? The possible duplicates in my case is a match in 2 objects in the array.

For example, I have the input:

const input = [
  {
    id: 1,
    name: "Test 1",
    value: 5,
    date: '2021-01-01'
  },
  {
    id: 2,
    name: "Test 2",
    value: 4,
    date: '2021-01-01'
  },
  {
    id: 3,
    name: "Test 3",
    value: 5,
    date: '2021-01-01'
  },
  {
    id: 4,
    name: "Test 4",
    value: 5,
    date: '2021-03-01'
  },
  {
    id: 5,
    name: "Test 1",
    value: 15,
    date: '2021-01-21'
  },
];

In this case the objects with id 1 and 3 are possible duplicates because they have the same value and date. I'm creating a new array for my output:

let output = [];
for(const x of input) {
  output.push(
    {
      id: x.id,
      name: x.name,
      value: x.value,
      date: x.date,
      duplicate: // here is where I would like to set it to true or false
    }
  );
}

Is there a way to do it without looping the array and check the value and date for every instance?

Thanks

2 Answers 2

1

Most efficient way is loop through data once and count instances where date + '|' + value occur.

Then map the data and check the counter for dups

const counter = new Map();

input.forEach(({value,date})=> {
    const key = `${date}|${value}`;
    counter.set(key, (counter.get(key) || 0) + 1);
});

const res = input.map(o => {
    const key = `${o.date}|${o.value}`;
    return {...o, duplicate: counter.get(key) > 1} ;
});



console.log(res)
.as-console-wrapper {max-height: 100%!important;top:0;}
<script>
 const input=[{id:1,name:"Test 1",value:5,date:"2021-01-01"},{id:2,name:"Test 2",value:4,date:"2021-01-01"},{id:3,name:"Test 3",value:5,date:"2021-01-01"},{id:4,name:"Test 4",value:5,date:"2021-03-01"},{id:5,name:"Test 1",value:15,date:"2021-01-21"}];
</script>

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

1 Comment

Thank you. Very smart solution. You keep everything in O(N) time.
0

Whatever solution you find, it WILL be looping through the array in the back kitchen. That's just the only way. That said here's a solution I find elegant:

let output = [];
for(const x of input) {
  output.push(
    {
      id: x.id,
      name: x.name,
      value: x.value,
      date: x.date,
      duplicate: output.some(e => e.value === x.value && e.date === x.date)
    }
  );
}

EDIT: If you want all occurences to have duplicate: true :

let output = [];
for(const x of input) {
  output.push(
    {
      id: x.id,
      name: x.name,
      value: x.value,
      date: x.date,
      duplicate: output.some(e => {
        if (e.value === x.value && e.date === x.date) {
          e.duplicate = true;
          return true;
        }
        return false;
      })
    }
  );
}

Edit2: Using filter() and length

let output = [];
for(const x of input) {
  output.push(
    {
      id: x.id,
      name: x.name,
      value: x.value,
      date: x.date,
      duplicate: input.filter(e => e.value === x.value && e.date === x.date).length > 1
    }
  );
}

4 Comments

Thank you, yes, I can't think a way to avoid the double loop. I think you meant input.some instead of output.some. Right?
Actually, it will return true for everything because it will always match the current loop
No I meant output.some the first occurence will get pushed to output as non-duplicate but the second one will be pushed as duplicate since it was already in output. I thought that was what you wanted. Otherwise the edit solves that
Also fixed : || to &&

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.