# Testing equality of vectors in a 2 dimensional array

**URL:** <https://discourse.processing.org/t/testing-equality-of-vectors-in-a-2-dimensional-array/35389>\
**Category:** Coding Questions\
**Created:** [February 22, 2022, 11:25pm UTC](https://discourse.processing.org/t/testing-equality-of-vectors-in-a-2-dimensional-array/35389 "2022-02-22T23:25:30Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![arathorn76](https://avatars.discourse-cdn.com/v4/letter/a/4bbf92/32.png) [@arathorn76](https://discourse.processing.org/u/arathorn76)\
**Post date:** [February 22, 2022, 11:25pm UTC](https://discourse.processing.org/t/testing-equality-of-vectors-in-a-2-dimensional-array/35389/1 "2022-02-22T23:25:30Z")

</div>

Hello together,  
I have a problem testing equality of one line of a 2D array against a possible new line.

My goal is to add a new line only if a line with the same elements does not yet exist.  
To achieve this I wrote the following code:

```auto
class Evaluation {
  constructor() {
    this.lines = [];

  }

  addLines(cell) {
    for (let newLine of cell.neighbors) {
      // Suchen, ob es diese Zeile schon gibt
      let pushIt = true;
      for (let i = 0; i < this.lines.length; i++) {
        let lineExists = 0;
        for (let j = 0; j < newLine.length; j++) {
          if (this.lines[i].includes(newLine[j])) {
            //passenden Merker setzen
            lineExists += 1;
          }
        }
        if (lineExists == newLine.length) {
          pushIt = false;
        }
      }
      if (pushIt) {
        this.lines.push(newLine);
      }
    }
  }
}

```

cell is an object that contains a 2D array neighbors. Each element cell.neighbors[i] is an array of 4 p5.Vectors. I have 64 instances of cell objects, Evaluation.addLines is called for each of them.  
The cells live in a 4_4_4 grid.  
Evaluation.lines _ **should** _ become a list of all straight lines covering 4 cells, each line should be present once.  
After calling addLines for all 64 cells Evaluation.lines is a list of all straight lines covering 4 cells, each line is present _4 times_.

I do not care for the order of elements in each line and I can not ensure that the order is equal in 2 representations of any given line.  
That is why I thought it would be a good idea to loop over all existing lines (for(let i…) with a nested inner loop (for(let j…) where I count how many of the vectors in newLine are present in that particular existing line.  
If all Vectors are present (lineExists == newLine.length) I set the pushIt-flag false to not push that line into the lines-array.

While debugging I saw that sometimes pushIt is set to false, but after adding the neighbors of all 64 cells I still get 304 lines instead of the 76 lines I expect.

Can anybody tell me where my error lies and point me in the right direction please?

Best regards from Germany

PS: I edited the title to include “of vectors”

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [February 23, 2022, 5:20am UTC](https://discourse.processing.org/t/testing-equality-of-vectors-in-a-2-dimensional-array/35389/2 "2022-02-23T05:20:18Z")

</div>

> [@arathorn76](#):
>
> Can anybody tell me where my error lies and point me in the right direction please?

> [@arathorn76](#):
>
> `if (this.lines[i].includes(newLine[j])) {`

Basically we shouldn’t use method Array::[**includes()**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes) to compare objects.

B/c object comparison in JS doesn’t check their contents (properties & their values).

Instead such comparison action merely checks whether both memory addresses match:

```javascript
'use strict';

function setup() {
  noCanvas();

  const vec = createVector(), arr = [vec];

  print(arr.includes(vec)); // true
  print(arr.includes(createVector())); // false

  print(arr[0] == vec, arr[0] == createVector()) // true, false

  print(createVector() == createVector()); // false
  print(createVector().x == createVector().x); // true
}

```

> [@arathorn76](#):
>
> I do not care for the order of elements in each line and…

That actually makes the algorithm slightly more complex.

Just coded a double function which relies on method Array::**some()** for a customized object comparison:

> **[Array.prototype.some() - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some)**
>
> The some() method of Array instances tests whether
> at least one element in the array passes the test implemented by the provided
> function. It returns true if, in the array, it finds an element for which the provided function returns true;...

The idea is to clone the 2nd vector array row and then invoke Array::**some()** inside the 1st vector array row’s loop.

Inside Array::**some()**'s callback we use method p5.Vector.[**equals()**](https://p5js.org/reference/#/p5.Vector/equals) to check whether the contents of both vectors match.

Every time both vectors match we Array::**splice()** that vector outta the cloned 2nd vector array row:

> **[Array.prototype.splice() - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice)**
>
> The splice() method of Array instances changes the contents of an array by
> removing or replacing existing elements and/or adding new elements in place.

Otherwise, if Array::**some()** fails to find a match, we `break` from the loop.

That function returns `true` only if the cloned 2nd vector array row becomes empty:

```javascript
'use strict';

function setup() {
  noCanvas();

  const
    row = [
      createVector(PI, TAU),
      createVector(),
      createVector(RAD_TO_DEG, DEG_TO_RAD, Math.SQRT2),
      createVector(PI, TAU)
    ],
    
    equal = [
      createVector(RAD_TO_DEG, DEG_TO_RAD, Math.SQRT2),
      createVector(PI, TAU),
      createVector(PI, TAU),
      createVector()
    ],

    diff = [
      createVector(RAD_TO_DEG, DEG_TO_RAD, Math.SQRT2),
      createVector(PI, TAU),
      createVector(TAU, PI),
      createVector()
    ],

    same = [
      createVector(PI, TAU),
      createVector(PI, TAU),
      createVector(PI, TAU),
      createVector(PI, TAU)
    ];

  print(rowsContainSameVecs(row, equal)); // true
  print(rowsContainSameVecs(row, diff)); // false

  print(rowsContainSameVecs(row, row)); // true
  print(rowsContainSameVecs(equal, row)); // true
  print(rowsContainSameVecs(equal, diff)); // false

  print(rowsContainSameVecs(row, same)); // false
  print(rowsContainSameVecs(same, row)); // false
}

function rowsContainSameVecs(vecRowOne, vecRowTwo) {
  if (vecRowOne?.length != vecRowTwo?.length) return false;

  vecRowTwo = vecRowTwo.slice();

  for (const vecOne of vecRowOne)
    if (!vecRowTwo.some(removeIfSameVec, vecOne)) break;

  return !vecRowTwo.length;
}

function removeIfSameVec(vec, idx, arr) {
  const same = vec.equals(this);
  same && arr.splice(idx, 1);
  return same;
}

```

---

<div class="post-metadata">

**Author:** ![arathorn76](https://avatars.discourse-cdn.com/v4/letter/a/4bbf92/32.png) [@arathorn76](https://discourse.processing.org/u/arathorn76)\
**Post date:** [February 23, 2022, 12:46pm UTC](https://discourse.processing.org/t/testing-equality-of-vectors-in-a-2-dimensional-array/35389/3 "2022-02-23T12:46:53Z")

</div>

Thank you for your input and the coding you provided.  
I will implement and test it in my program and report back.

---

<div class="post-metadata">

**Author:** ![arathorn76](https://avatars.discourse-cdn.com/v4/letter/a/4bbf92/32.png) [@arathorn76](https://discourse.processing.org/u/arathorn76)\
**Post date:** [February 23, 2022, 4:34pm UTC](https://discourse.processing.org/t/testing-equality-of-vectors-in-a-2-dimensional-array/35389/4 "2022-02-23T16:34:58Z")

</div>

Here I am again…

I ended up not quite using the algorithm you provided. I may do so in the future and it may well be better than my algorithm, but…

- I´m a beginner in js
- I´m not (yet) comfortable with the idea and use of callback functions
- I don´t fully understand the benefit of your algorithm compared to mine.

What did I do?

```auto
  addLines(cell) {
    for (let newLine of cell.neighbors) {
      // Suchen, ob es diese Zeile schon gibt
      let pushIt = true;
      for (let i = 0; i < this.lines.length; i++) {
        let lineExists = 0;
        for (let j = 0; j < newLine.length; j++) {

// if (this.lines[i].includes(newLine[j])) {
// //passenden Merker setzen
// lineExists += 1;
// }
          for (let k = 0; k < this.lines[i].length; k++) {
            if (this.lines[i][k].equals(newLine[j])) {
              //count number of identical vectors per line
              lineExists += 1;
            }
          }

        }
        // if all vectors are identical
        if (lineExists == newLine.length) {
          pushIt = false;
          break;
        }
      }
      if (pushIt) {
        this.lines.push(newLine);
      }
    }
  }

```

I added a 4th layer of nested loops to go throug the elements of the existing line(s) and the new line to compare them.  
I used p5.Vector.equals() instead of == to compare the vectors. This is the core point I took from your suggestion and I´m sure it was my main mistake.

As far as I understand it the explicit check for same length in your function rowsContainSameVecs() is an improvement over my algorithm.  
I think that one is minor in my special case, as I ensure lines of length 4 at creation of my inputs.  
And your use of array.some() with your callback is presumably faster than my additional loop.

One point I don´t really understand is:  
what does the “this” point to in the line

````auto
  const same = vec.equals(this);
```?
````

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [February 23, 2022, 5:35pm UTC](https://discourse.processing.org/t/testing-equality-of-vectors-in-a-2-dimensional-array/35389/5 "2022-02-23T17:35:35Z")

</div>

> [@arathorn76](#):
>
> What does the `this` point to in the line?  
> `const same = vec.equals(this);`

That keyword `this` inside the callback **removeIfSameVec(_vec_, _idx_, _arr_)** refers to the 2nd parameter from method Array::[**some(_callbackFn_, _thisArg_)**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some):

> [@GoToLoop](#):
>
> ```auto
> for (const vecOne of vecRowOne)
> if (!vecRowTwo.some(removeIfSameVec, vecOne)) break;
> 
> ```

So it’s comparing each p5.Vector object from _vecRowTwo[]_ cloned array to the current p5.Vector object (represented by loop’s iterator _vecOne_) from _vecRowOne[]_ array.

If they’re **equals()**, I use Array::[**splice(_startIndex_, _deleteCount_)**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice) method to delete the current index from _vecRowTwo[]_ cloned array (represented by callback’s parameter _arr_) to make sure that p5.Vector isn’t found again for the rest of the loop:

> [@GoToLoop](#):
>
> `same && arr.splice(idx, 1);`

At the end of the loop it’s expected for _vecRowTwo[]_ cloned array to be empty (its _length_ = 0):

> [@GoToLoop](#):
>
> `return !vecRowTwo.length;`

If so, it means that each p5.Vector object from _vecRowOne[]_ array has found an **equals()** among _vecRowTwo[]_ cloned array.

---

<div class="post-metadata">

**Author:** ![arathorn76](https://avatars.discourse-cdn.com/v4/letter/a/4bbf92/32.png) [@arathorn76](https://discourse.processing.org/u/arathorn76)\
**Post date:** [February 23, 2022, 7:23pm UTC](https://discourse.processing.org/t/testing-equality-of-vectors-in-a-2-dimensional-array/35389/6 "2022-02-23T19:23:53Z")

</div>

Thank you again for the additional explanations.

At the moment my problem is solved.  
I will make a note to try out your suggested algorithm to see if it makes an improvement over the solution I chose for now.

I have a lot more to learn about javascript and your explanations helped me a lot to that end.
