0

What is the best way to check if two arrays have the same/equal values (in any order) in JavaScript?

These values are just a primary keys of database entities, so they always will be different

const result = [1, 3, 8, 77]
const same = [8, 3, 1, 77]
const diff = [8, 3, 5, 77]

areValuesTheSame(result, same) // true
areValuesTheSame(result, diff) // false

How should areValuesTheSame method look like?

P.S. This question looks like a duplicate but I didn't find anything relative to Javascript.

Yegor Zaremba
  • 3,188
  • 3
  • 20
  • 41

3 Answers3

3

I'm making the following assumptions:

  • The arrays only contain numbers.
  • You don't care about the order of the elements; rearranging the arrays is OK.

Under those conditions we can simply convert each array to a canonical string by sorting it and joining the elements with e.g. a space. Then (multi-)set equality boils down to simple string equality.

function areValuesTheSame(a, b) {
    return a.sort().join(' ') === b.sort().join(' ');
}

const result = [1, 3, 8, 77];
const same = [8, 3, 1, 77];
const diff = [8, 3, 5, 77];

console.log(areValuesTheSame(result, same));
console.log(areValuesTheSame(result, diff));

This is probably the laziest / shortest approach.

melpomene
  • 81,915
  • 7
  • 76
  • 137
  • @MisterJojo Yes, that's what I said (assumption #2). – melpomene Jun 23 '19 at 17:27
  • your answer is so good, cause its more understandable, as someone mentioned in question, order/values place isn't matter(and it's my case), so I'll accept your solution. But @ghoul-ahmed have a nice one, too) – Yegor Zaremba Jun 23 '19 at 17:36
  • You could also use `JSON.stringify` instead of join, to make it also work for string or any other primitive arrays. – georg Jun 23 '19 at 18:42
2

You could count all elements with a Map (this is type save) up for the one array and down for the other and check if all items have a final count of zero.

function haveSameValues(a, b) {
    const count = d => (m, v) => m.set(v, (m.get(v) || 0) + d)
    return Array
        .from(b.reduce(count(-1), a.reduce(count(1), new Map)).values())
        .every(v => v === 0);
}

const result = [1, 3, 8, 77]
const same = [8, 3, 1, 77]
const diff = [8, 3, 5, 77]

console.log(haveSameValues(result, same)); // true
console.log(haveSameValues(result, diff)); // false
Nina Scholz
  • 351,820
  • 24
  • 303
  • 358
1

Try this:

const result = [1, 3, 8, 77]
const same = [8, 3, 1, 77]
const diff = [8, 3, 5, 77]
const areValuesTheSame = (a,b) => (a.length === b.length) && Object.keys(a.sort()).every(i=>a[i] === b.sort()[i])


console.log(areValuesTheSame(result, same)) // true
console.log(areValuesTheSame(result, diff)) // false
Mister Jojo
  • 16,804
  • 3
  • 16
  • 39
Ghoul Ahmed
  • 4,012
  • 1
  • 13
  • 22
  • 1
    That doesn't work at all. If you add `9` to `same` (as in `[8, 3, 1, 77, 9]`), it still thinks it's equal to `result`. – melpomene Jun 23 '19 at 16:57
  • Instead of `Object.keys()`, just use `a.sort(), b.sort().every((x, i) => x == a[i])`. Especially don't call `b.sort()` during every comparison! – Bergi Jun 23 '19 at 17:53
  • @MisterJojo If order doesn't matter, it probably doesn't matter to change it. If it matters, it's trivial to clone the arrays beforehand. – Bergi Jun 23 '19 at 17:53