1

Problem

Given the following two arrays:

const myArr1 = [
 { locationPath: 'R0', locationOnGrid: { x: '0', y: '0' } }, // same as second in myArr2
 { locationPath: 'U5', locationOnGrid: { x: '1', y: '0' } },
 { locationPath: 'L3', locationOnGrid: { x: '3', y: '7' } } // same as second in myArr2
]

const myArr2 = [
 { locationPath: 'D0', locationOnGrid: { x: '0', y: '0' } }, // same as second in myArr1
 { locationPath: 'L5', locationOnGrid: { x: '3', y: '7' } }, // same as third in myArr1
 { locationPath: 'L7', locationOnGrid: { x: '0', y: '1' } },
 { locationPath: 'R2', locationOnGrid: { x: '2', y: '2' } }
]

// Do something to 'filter' out the objects that are similar.

Result

Then what I would like to also be able to do after the comparison has been made, is to filter out a certain result:

// Result of the 'filter' function
const found = [
  { locationPath: 'R0', locationOnGrid: { x: '0', y: '0' } },
  { locationPath: 'L5', locationOnGrid: { x: '3', y: '7' } }
];

// and want to do something like the following on the found array:
const startingPoint = ({locationOnGrid}) => {
    return JSON.stringify(locationOnGrid) !== JSON.stringify({ x: '0', y: '0' });
};
const filteredFound = found.filter(startingPoint);
console.log(filteredFound);

// output:
// Array(1)
// 0: {locationPath: "L5", locationOnGrid: {…}}

What I've tried so far:

There are some Stackoverflow questions that relate to the comparison between two Arrays. For example the question Simplest code for array intersection and How to filter array by comparing two elements comes really close.

// does not work
const found = myArr2.filter((item, index) => {
  return
  (
    item.locationOnGrid.x === myArr1[index].locationOnGrid.x &&
    item.locationOnGrid.y === myArr1[index].locationOnGrid.y
  );
});
console.log(found);

Also two arrays don't always necessarily have the same amount of objects. In the example myArr2 has 1 more object. So this works. But for another scenario it could very well be that myArr1 has more objects than myArr2.

Remi
  • 4,663
  • 11
  • 49
  • 84
  • 3
    why `'L5'` and not `'L3'`? – Nina Scholz Dec 05 '19 at 08:42
  • Those are generated. So those don't have to be equal. – Remi Dec 05 '19 at 08:43
  • @Remi in the output, first object is taken from array 1 and second object is taken from second array, why it is not taken from first array. that is what Nina is asking – Kiran Shinde Dec 05 '19 at 08:45
  • @Remi Why does the `found` array contain `[R0, L5]` and not `[R0, L3]` or `[D0, L5]`? – nick zoum Dec 05 '19 at 08:47
  • @nickzoum only the ones that have x and y similar should go into the 'found' array. – Remi Dec 05 '19 at 08:49
  • 1
    @Remi `R0` and `D0` have the same coordinates, `L3` and `L5` have the same coordinates. why is the result `[R0, L5]` and not `[R0, L3]` or `[D0, L5]`? – nick zoum Dec 05 '19 at 08:50
  • @nina-scholz (&Kenny) That was my attempt to compare a value of myArr1 to myArr2. – Remi Dec 05 '19 at 08:50
  • Ah I see now. Good point on the coordinates. I need to think about it for a minute what is the desired outcome. I'll adjust the question with this info. – Remi Dec 05 '19 at 08:53

1 Answers1

2

You could get a Set with normalised key/value pairs, ordered by the key and create a JSON.

Then filter the first array and get the common locationOnGrid objects.

const
    stringified = o => JSON.stringify(Object.entries(o).sort((a, b) => a[0].localeCompare(b[0]))),
    array1 = [{ locationPath: 'R0', locationOnGrid: { x: '0', y: '0' } }, { locationPath: 'U5', locationOnGrid: { x: '1', y: '0' } }, { locationPath: 'L3', locationOnGrid: { x: '3', y: '7' } }],
    array2 = [{ locationPath: 'D0', locationOnGrid: { x: '0', y: '0' } }, { locationPath: 'L5', locationOnGrid: { x: '3', y: '7' } }, { locationPath: 'L7', locationOnGrid: { x: '0', y: '1' } }, { locationPath: 'R2', locationOnGrid: { x: '2', y: '2' } }],
    set2 = new Set(array2.map(({ locationOnGrid }) => stringified(locationOnGrid))),
    common = array1.filter(({ locationOnGrid }) => set2.has(stringified(locationOnGrid)));

console.log(common);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Brilliant. Regarding your earlier question, why 'L5' and not 'L3'. In this answer you get L3. If you'd were to switch the two arrays (`array1.map(...` and `array2.filter`) you'd get 'L3' instead of 'L5'. Great! – Remi Dec 05 '19 at 09:08