0

I have a simple script that makes a fixture matching all values of an array against all.

const players = ['a', 'b', 'c', 'd'];
const matches = [];

players.forEach(k => {
  players.forEach(j => {
    if(k !== j) {
      let z = [k, j]
      z.sort()
      const inArray = matches.indexOf(z) !== -1

      if(!inArray) matches.push(z)

      console.log(matches)
    }

  })
})

Although asking Javascript search for if z is in matches array, the result has duplicated items and returns this:

[ 'a', 'b' ]​​​​​​

​​​​​[ 'a', 'c' ]​​​​​​

​​​​​[ 'a', 'd' ]​​​​​​

​​​​​[ 'a', 'b' ]​​​​​​ --> duplicated item

​​​​​[ 'b', 'c' ]​​​​​​

​​​​​[ 'b', 'd' ]​​​​​​

​​​​​[ 'a', 'c' ]​​​​​​ --> duplicated item

​​​​​[ 'b', 'c' ]​​​​​​ --> duplicated item

​​​​​[ 'c', 'd' ]​​​​​​

​​​​​[ 'a', 'd' ]​​​​​​ --> duplicated item

​​​​​[ 'b', 'd' ]​​​​​​ --> duplicated item

​​​​​[ 'c', 'd' ]​​​​​​ --> duplicated item

How can avoid these duplicated items?

5
  • indexOf() doesn't take an array. Commented Jan 5, 2018 at 0:42
  • 1
    indexOf looks for equality, so only primitives will really work like that. ie: "a" === "a" // true, but [] === [] // false. Try looking at this question Commented Jan 5, 2018 at 0:47
  • Why are you calling z.sort()? Commented Jan 5, 2018 at 0:54
  • They are not duplicates. It's because you are sorting them (e.g. your 2nd ['a', 'b'] is actually ['b', 'a'] Commented Jan 5, 2018 at 0:55
  • How about a solution that doesn't generate these duplicates in the first place? players.forEach((v,i,a) => { while(++i < a.length) matches.push([v, a[i]]) }) or Array.from(new Set(players)).forEach(...) if players itself may contain duplicates. Commented Jan 5, 2018 at 7:40

2 Answers 2

2

I'm assuming you meant if(!inArray) matches.push(z), right? Either way, indexOf will not compare the values of Arrays, but rather it is actually checking for referential equivalence, i.e. whether the Array instances themselves are equal.

In order to properly compare the values of your arrays, you'll probably want to write a helper function to use instead of indexOf. Luckily, this answer explains how to do just that.

Additionally, here is a great article on MDN which breaks down various kinds of equality comparisons.

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

Comments

0

If the array items will always be strings, you could do something a little hacky, but will get the job done

const players = ['a', 'b', 'c', 'd'];
const matches = [];

players.forEach(k => {
  players.forEach(j => {
    if(k !== j) {
      let z = [k, j];

      z.sort()
      const inArray = matches.map(match=>match.join('')).indexOf(z.join('')) !== -1

      if(!inArray) matches.push(z)

      console.log(matches)
    }

  })
})

Basically you are turning the arrays into strings just before comparison which gives javascript a way to check to see if they are equal. Checking equality across array instances doesn't work and will return undesired results.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.