0

Here is some typescript code that I have in a NexJS app:

const holeSet:any[] = [];
.....

let xx = 1, yy = 2;
holeSet.push({x:xx,y:yy});

xx = 3;
yy = 4;
holeSet.push({x:xx,y:yy});

holeSet.map((e) => {
  console.log("element ::"+JSON.stringify(e));
});

const a = 1;
const b = 2;

if (holeSet.includes({x:a.toString(),y:b.toString()}))
  console.log("Value {1;2} FOUND !");

Here is the output produced when running the code above:

element ::{"x":1,"y":2} element ::{"x":3,"y":4}

My problem is that I do not know what I am doing wrong.

I expect the message: Value {1;2} FOUND !

to show up, but it does not happen. Why is that ?

A bad syntax in the if statement I assume ??

4
  • @jcalz I searched for a duplicate before answering, but did not find one. Can you provide a URL to the search query view that you used to discover the one that you linked? Commented Aug 7, 2024 at 1:17
  • This was my search (using Google and not Stack Overflow's search feature) Commented Aug 7, 2024 at 1:20
  • ^ Thanks — SO search really needs improvement… Commented Aug 7, 2024 at 1:23
  • Array.prototype.includes uses strict equality (===) to check if an element exists in an array. For example: const x = {xx: 1, yy: 2}; const y = {xx: 1, yy: 2}; x !== y because they reference different objects in heap memory. So, the holeSet.includes({...}) returns false. Use holeSet.map(el => JSON.stringify(el)).includes(JSON.stringify({...})) or holeSet.some(el => el.xx === a && el.yy === b) or try lodash utility library for deep comparison. Refer this question Commented Aug 7, 2024 at 4:25

2 Answers 2

2

Usage of object literal syntax creates a new object. For example, in the code you showed:

holeSet.push({ x: xx, y: yy });
//           ^^^^^^^^^^^^^^^^

and

if (holeSet.includes({ x: a.toString(), y: b.toString() }))
//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

…these create new, unique objects.

Array.prototype.includes() uses same-value-zero equality to compare the first argument provided to each array element (in the spec this is called the SameValueZero algorithm). Two unique objects will never be equal to each other using that algorithm, so… using object literal syntax to create the first argument value when invoking holeSeet.includes will always return false:

holeSet.includes({ x: a.toString(), y: b.toString() })
//               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Using a unique object for this argument will always return `false`

You can use Array.prototype.some() to determine if one of the elements has the expected shape by using a function that compares the values of the properties x and y to the expected values:

if (holeSet.some((o) => o.x === a && o.y === b))

Code in the TypeScript Playground

This will result in the condition evaluating to true and you'll see the expected message in the console.

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

Comments

1

The problem you are experiencing here is the way that includes works, when comparing objects they are compared by reference, not value. So it is attempting to check if it is the same object which it never will be. To overcome this I would use something as such:

holeSet.some(e => e.x === a && e.y === b)

This will check the values of each object within the array and I believe work as you expect the includes to.

2 Comments

It actually works both with: "if (holeSet.some((o) => o.x===j && o.y===i))" and with: "if (holeSet.some((o) => o.x==j && o.y==i))"
That should be the same thing, I just forgot the if :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.