3

I have array of objects.

let coordinates = [
    { x: 8, y: 1 },
    { x: 8, y: 3 },
    { x: 6, y: 5 },
    { x: 4, y: 6 },
    { x: 3, y: 7 },
    { x: 6, y: 5 },
    { x: 3, y: 3 },
    { x: 1, y: 4 },
    { x: 3, y: 3 }
]

I stumbled upon this blog and this stackoverflow question but it only lets me find duplicates based on one property but I want to get the duplicate objects based on x and y properties like this:

[
    { x: 6, y: 5 },
    { x: 3, y: 3 }
]
2
  • what is expected result? Commented May 24, 2020 at 6:48
  • 1
    @brk it's in the last part of my question Commented May 24, 2020 at 6:52

4 Answers 4

2

We apply filter to check the uniquness of index, say if element is duplicate it will count the initial index and the current index will be filtered out.

var coordinates = [ { x: 8, y: 1 }, { x: 6, y: 5 }, { x: 4, y: 6 }, { x: 3, y: 7 }, { x: 6, y: 5 }, { x: 3, y: 3 }, { x: 1, y: 4 }, { x: 3, y: 3 }];

var result = coordinates.filter((val, i, self)=>self.findIndex(k=>k.x==val.x && k.y == val.y)!=i);

console.log(result)

UPDATE

coordinates = [ { x: 6, y: 5 }, { x: 6, y: 5 }, { x: 6, y: 5 },{ x: 4, y: 6 }, { x: 3, y: 7 }, { x: 6, y: 5 }, { x: 3, y: 3 }, { x: 3, y: 3 }, { x: 1, y: 4 }, { x: 3, y: 3 },{ x: 6, y: 5 }];

result = coordinates.reduce((acc, elem)=>{
  key = Object.values(elem).join('|');
  acc.unique[key] = acc.unique[key] || [];
  acc.unique[key].length >0 ? acc.duplicate[key] = elem : acc.unique[key].push(elem);
  return acc;
},{unique:{},duplicate:{}});

duplicate = Object.values(result.duplicate);
unique = Object.values(result.unique);

console.log(duplicate);
console.log(unique);

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

2 Comments

@breekoy Also if you look at filter function it accepts various arguments such as (val, i, self) val representing current iteration element, i representing index count and self is the array itself.
This is wrong answer. It breaks with array consists of duplicates more than 2 var coordinates = [ { x: 3, y: 3 }, { x: 3, y: 3 }, { x: 3, y: 3 }, ]
1

All the answers are not fully correct, because they don't apply to arrays with more than 2 duplicates of the same value, i.e.:

var coordinates = [
  { x: 8, y: 1 },
  { x: 8, y: 1 },
  { x: 8, y: 1 }
]

I used JSON.stringify() and Set structure to get unique duplicates from an array. And for the output I parsed strings back to the objects.

var coordinates = [
      { x: 8, y: 1 },
      { x: 6, y: 5 },
      { x: 4, y: 6 },
      { x: 3, y: 7 },
      { x: 6, y: 5 },
      { x: 3, y: 3 },
      { x: 1, y: 4 },
      { x: 3, y: 3 },
      { x: 3, y: 3 },
]
    
const duplicates = new Set();
const reducer = (set, val, index, arr) => arr.findIndex(k => k.x == val.x && k.y == val.y) != index ? set.add(JSON.stringify(val)) : set
    
coordinates.reduce(reducer, duplicates)
    
console.log(Array.from(duplicates).map(el => JSON.parse(el)))

Comments

1

You can use reduce and another array. Inside reduce callback use x & y to create an object key and check if that key exist in accumulator object. If it exist then push tyhe value to the dupArray

let coordinates = [
  { x: 8, y: 1 },
  { x: 8, y: 3 },
  { x: 6, y: 5 },
  { x: 4, y: 6 },
  { x: 3, y: 7 },
  { x: 6, y: 5 },
  { x: 3, y: 3 },
  { x: 1, y: 4 },
  { x: 3, y: 3 }
];
let dupArray = [];
let dups = coordinates.reduce((acc, curr) => {
  const crtKey = '' + curr.x + '' + curr.y;
  if (!acc[crtKey]) {
    acc[crtKey] = 1;
  } else {
    dupArray.push(curr);
  }
  return acc;
}, {});

console.log(dupArray)

10 Comments

I think that the first '' before + curr.x is redundant
@zb22 because i want the key to be string otherwise key weill be numeric for example a key like 9(6+3) or 9(5+4) will be same, which will give wrong result
yes, but the curr.x + '' + curr.y makes it to be a string, once you put the '' between them
This answer also breaks with more than 2 duplicates var coordinates = [ { x: 3, y: 3 }, { x: 3, y: 3 }, { x: 3, y: 3 }, ]
This is intuitive when we want duplicates, we don't need duplicated duplicates. Only unique duplicates.
|
0

this filters only the duplicate array Objects by iterating all the Array items and for each item, iterating the Array again, using some to check if that specific item was anywhere in the array (arr) in a location before the current one (idx1) and also comparing the current item with the checked items in the some iterator by casting both to "string"

let coordinates = [
    { x: 8, y: 1 },
    { x: 8, y: 3 },
    { x: 6, y: 5 },
    { x: 4, y: 6 },
    { x: 3, y: 7 },
    { x: 6, y: 5 },
    { x: 3, y: 3 },
    { x: 1, y: 4 },
    { x: 3, y: 3 }
]

const dups = coordinates.filter(({x, y}, idx1, arr) => 
    arr.some(({x:x2,y:y2}, idx2) => idx2 < idx1 && ""+x+y == ""+x2+y2 ) 
)

console.log( dups )

To make the check more robust, by allowing comparison of any key, what-so-ever JSON.stringify can be used to compare the arrays (assuming all array items are Objects:

const dups = coordinates.filter((item, idx1, arr) => 
   arr.some((item2, idx2) => idx2 < idx1 && JSON.stringify(item) == JSON.stringify(item2)) 

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.