8

In this answer there is a simple function that will return array equality for arrays that contain primitive values.

However, I'm not sure why it works. Here is the function:

function arrays_equal(a,b) { return !!a && !!b && !(a<b || b<a); }

I'm mostly interested in the second half; this bit:

!(a<b || b<a)

Why does the < and > work when comparing the arrays but the == doesn't?

How do the less than and greater than methods work within JavaScript?

0

3 Answers 3

11

With </>, the arrays are converted to strings first, and as such do not provide a reliable method of checking equality.

== does not work because objects are checked by reference:

[] == []; // false, two separate objects

var a = [];
a == a; // true, refer to the same object

The </> trick is flawed:

var a = [1, [2, 3]],
    b = [[1, 2], 3];

!(a<b || b<a); // true

This evaluates to true, because they are both converted to the string "1,2,3" before they are checked (</> do not "directly" work for objects).

So basically, you are comparing equality of the strings. For strings, a == b is indeed the same as !(a<b || b<a) - </> for strings check character codes, so two equal strings are neither "smaller" nor "greater" because that's not the case for any character code in the strings.

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

14 Comments

A more reliable alternative might be JSON.stringify(a) == JSON.stringify(b).
@gilly: True, unless the arrays contain objects themselves.
@gilly3: There'll be other issues as well. JSON.stringify([function(){}]) == JSON.stringify([,]) // true.
@Heera: Ah I missed that - I don't know those codes off the top of my head :) Yes, you're correct, but note that the commas are also in the string. Anyway, consider a more trivial example: "1" > "2" is false because 49 > 50 is false. Likewise, the opposite is true.
The point of most of these arguments is basically that you can't use something simple like this as a generic utility function. But, from a more practical standpoint, if your arrays are in a known format (eg, comparing two simple string arrays), a function like this is certainly adequate.
|
5

However, I'm not sure why it works.

It doesn't work. Consider

arrays_equal(["1,2"], [1,2])

produces true even though by any definition of array equality based on element-wise comparison, they are different.

arrays_equal([[]], [])

and

arrays_equal([""], [])

are also spurious positives.

Simply adding length checking won't help as demonstrated by

arrays_equal(["1,2",3], [1,"2,3"])

arrays_equal(
    ["",","],
    [",",""])

EDIT:

If you want a succinct way to test structural similarity, I suggest:

function structurallyEquivalent(a, b) {
  return JSON.stringify(a) === JSON.stringify(b);
}

It doesn't stop early on inputs that are obviously different -- it walks both object graphs regardless of how disimilar they are, but so does the function in the OP.

One caveat: when you're using non-native JSON.stringify, it may do strange things for cyclic inputs like:

var input = [];
input[0] = input;

3 Comments

Even for primitives, JSON.stringify might not be fully reliable. Consider [,] and [null].
@pimvdb, Sure. It conflates null and undefined/elipsis but so does JavaScript ==. Nothing in the OP expresses a preference for === over ==.
Thanks, your answer further aided in my understanding along with @pimvdb's.
4

You can compare any two objects using ==. But since > and < are not defined for objects, they are converted to strings. Therefore, [1,2,3]>[2,1,3] is actually doing "1,2,3">"2,1,3"

2 Comments

this is not correct. Conversion is not always to string. 11.8.5 specifies that object conversion happens with type hint "number" so arrays_equal(new Date(1), 1) is true.
Thanks; and to Mike for the clarification in his comment!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.