13

I am using React's componentDidUpdate lifecycle method.

I am trying to determine whether or not two arrays are the same.

My prevState array looks like this:

prevState.players = [
  {
    name: 'Wayne Rooney',
    age: 31
  }, 
  {
    name: 'Lionel Messi',
    age: 29
  },
  {
    name: 'Robbie Fowler',
    age: 42
  }
];

and the this.state array looks like this:

this.state.players = [
  {
    name: 'Wayne Rooney',
    age: 31
  }, 
  {
    name: 'Lionel Messi',
    age: 29
  },
  {
    name: 'Robbie Fowler',
    age: 42
  }
];

As you can see if you expand the snippet below they are not equal:

let playersOne = [{
    name: 'Wayne Rooney',
    age: 31
  },
  {
    name: 'Lionel Messi',
    age: 29
  },
  {
    name: 'Robbie Fowler',
    age: 42
  }
];

let playersTwo = [{
    name: 'Wayne Rooney',
    age: 31
  },
  {
    name: 'Lionel Messi',
    age: 29
  },
  {
    name: 'Robbie Fowler',
    age: 42
  }
];

console.log(playersOne == playersTwo)

And here is my react lifecycle code.

  componentDidUpdate(prevProps, prevState) {
    if(prevState.players != this.state.players) {
      this.updatePlayers(this.state);
    }
  }

can anyone advise as to the best way to determine if the arrays are equal?

peter flanagan
  • 9,195
  • 26
  • 73
  • 127
  • 2
    Duplicates https://stackoverflow.com/questions/201183/how-to-determine-equality-for-two-javascript-objects and https://stackoverflow.com/questions/1068834/object-comparison-in-javascript – Salman A Feb 06 '18 at 09:18
  • 4
    `JSON.stringify(playersOne) == JSON.stringify(playersTwo)` – Akash Dathan Feb 06 '18 at 09:19
  • @AkashDathan looks like that one will do it – peter flanagan Feb 06 '18 at 09:20
  • One thing that React docs suggest is to use Immutable data since such comparisons can be expensive, but you still need to do it use _.isEqual from lodash or deep compare individual values – Shubham Khatri Feb 06 '18 at 09:21
  • check all the results [**here**](https://www.google.co.in/search?q=how+to+check+two+arrays+of+objects+are+equal+in+javascript+site:stackoverflow.com&sa=X&ved=0ahUKEwib6IXV-5DZAhVDvY8KHdswDrkQrQIIMygEMAA&biw=1440&bih=803) – Mayank Shukla Feb 06 '18 at 09:26

4 Answers4

43

JSON.stringify(playersOne) == JSON.stringify(playersTwo)

Akash Dathan
  • 4,348
  • 2
  • 24
  • 45
  • 8
    HAHAHAHA i love this – DarkArtistry Jan 12 '19 at 02:51
  • 3
    This will backfire if your objects contain cyclic references. the JSON.stringify() method will not work correctly. – Fëamarto May 21 '19 at 09:41
  • 1
    This is also a bad idea if you care about the order of keys in an object.... `JSON.stringify({a: 1, b: 2}) !== JSON.stringify({b: 2, a: 1});` – Adzz Jul 29 '20 at 11:50
  • @Adzz your example disproves your statement, did you mean "if you don't care about the order of keys" ? – Akash Dathan Jul 29 '20 at 14:15
  • Whoops, yea typo. If you think the two in the example should be equal, using `JSON.stringify` they would not be. – Adzz Jul 29 '20 at 14:25
  • This is dangerous territory and will not work for cyclic references (i.e an array of objects with other objects etc.). – Jason Rice Jun 07 '21 at 19:20
5
  1. Using _.isEqual from lodash;
  2. Using JSON.stringify and comparing the strings;
Bsalex
  • 2,847
  • 1
  • 15
  • 22
4

You can use array.prototype.every :

var players = [
  { name: 'Wayne Rooney'  , age: 31 }, 
  { name: 'Lionel Messi'  , age: 29 },
  { name: 'Robbie Fowler' , age: 42 }
];

var statePlayers = [
  { name: 'Wayne Rooney'  , age: 31 }, 
  { name: 'Lionel Messi'  , age: 29 },
  { name: 'Robbie Fowler' , age: 42 }
];

var equals = players.length === statePlayers.length && players.every((e, i) => e.name === statePlayers[i].name && e.age === statePlayers[i].age);

console.log(equals);

Alternatively, using object destructuring and Array.prototype.some.

const
  players = [
    { name: 'Wayne Rooney'  , age: 31 }, 
    { name: 'Lionel Messi'  , age: 29 },
    { name: 'Robbie Fowler' , age: 42 }
  ],
  statePlayers = [
    { name: 'Wayne Rooney'  , age: 31 }, 
    { name: 'Lionel Messi'  , age: 29 },
    { name: 'Robbie Fowler' , age: 42 }
  ],
  playersEqual = (expected, actual) =>
    actual.length === expected.length &&
      !expected.some(({ name, age }, i) =>
        (({ name: otherName, age: otherAge }) =>
          name !== otherName || age !== otherAge)
        (actual[i]));

console.log(playersEqual(players, statePlayers));
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
Faly
  • 13,291
  • 2
  • 19
  • 37
4

You can use array#every to check if both objects have the same number of objects and each object has the same number of key and values.

let playersOne = [{ name: 'Wayne Rooney', age: 31 }, { name: 'Lionel Messi', age: 29 }, { name: 'Robbie Fowler', age: 42 } ],
    playersTwo = [{ name: 'Wayne Rooney', age: 31 }, { name: 'Lionel Messi', age: 29 }, { name: 'Robbie Fowler', age: 42 } ];
 var isSame = playersOne.length === playersTwo.length && playersOne.every((o,i) => Object.keys(o).length === Object.keys(playersTwo[i]).length && Object.keys(o).every(k => o[k] === playersTwo[i][k]));
console.log(isSame);
Hassan Imam
  • 21,956
  • 5
  • 41
  • 51
  • Good, but I think it would be potentially a bit more efficient to use `.some` and `!==` in the lambda to check if either of the arrays is missing an element of the other. – Josh M. May 22 '20 at 12:50