Combined Comparison / "Spaceship" Operator (<=>) in Javascript?

15,569

Solution 1

As far as I know there is no such operator in JavaScript but you can use Math.sign() function:

Math.sign(a - b);

NOTE: As was mentioned in comments, Math.sign() is not currently supported by all browsers. Check for compatibility (MDN).

Solution 2

from: http://sabrelabs.com/post/48201437312/javascript-spaceship-operator

improved version:

function spaceship(val1, val2) {
  if ((val1 === null || val2 === null) || (typeof val1 != typeof val2)) {
    return null;
  }
  if (typeof val1 === 'string') {
    return (val1).localeCompare(val2);
  } else {
    if (val1 > val2) {
      return 1;
    } else if (val1 < val2) {
      return -1;
    }
    return 0;
  }
}

Solution 3

Here is a one-liner for current js ES2020?:

const spaceship = (a, b) => (a ?? 0).toString().localeCompare((b ?? 0).toString());

Returns string comparison for everything.

Share:
15,569

Related videos on Youtube

Kaspar Lee
Author by

Kaspar Lee

Updated on June 16, 2022

Comments

  • Kaspar Lee
    Kaspar Lee almost 2 years

    Ruby has something called a Combined Comparison or "Spaceship" Operator, it looks like this: <=>

    It does the following:

    a <=> b :=
        if a < b then return -1
        if a = b then return  0
        if a > b then return  1
    

    Credit

    Is there a similar Operator in Javascript? If not, how can I end up with the same result?


    @madox2 suggested using Math.sign(a - b), which works for number, but not arrays (to compare arrays you need to use array.length).

    It also does not work in Internet Explorer, Safari or all Mobile Browsers (see MDN)


    @duques_l found a function here. It works very well, you can test it on JSFiddle

    The only problem is if the strings are not comparable the function returns -1 instead of nil

    Update: @duques_l changed the function a bit and now it works fine (I think so anyway, here is the JSFiddle):

    function spaceship(val1, val2) {
        if ((val1 === null || val2 === null) || (typeof val1 != typeof val2)) {
            return null;
        }
        if (typeof val1 === 'string') {
            return (val1).localeCompare(val2);
        }
        else {
            if (val1 > val2) { return 1 }
            else if (val1 < val2) { return -1 }
            return 0;
        }
    }
    

  • Kaspar Lee
    Kaspar Lee over 8 years
    This works for numbers, but not arrays (well, you have to use array.length). Clever solution though!
  • Nina Scholz
    Nina Scholz over 8 years
    if there is one, not in ie.
  • Kaspar Lee
    Kaspar Lee over 8 years
    @NinaScholz If there is one what?
  • Nina Scholz
    Nina Scholz over 8 years
    @Druzion, the Internet Explorer does not have Math.sign().
  • Kaspar Lee
    Kaspar Lee over 8 years
    @NinaScholz Ah yes, it is also not supported in Safari and all Mobile Browsers, according to MDN
  • Kaspar Lee
    Kaspar Lee over 8 years
    No, if the data types are different, it returns 0. Check the new JSFiddle
  • Léo
    Léo over 8 years
    it's fixed, can you check ?
  • Léo
    Léo over 8 years
    nil doesn't exist in javascript, it's null
  • Romain 'Maz' BILLOIR
    Romain 'Maz' BILLOIR almost 3 years
    As of today and according to CanIUse.com : Math.sign is supported by almost 95% browsers. If your target clients is that guys who update their browsers, you can assume it's now safe to use it.
  • Manngo
    Manngo about 2 years
    For those desperate to support Legacy Browsers: if(!Math.sign) Math.sign=function(value) {return value?(value<0?-1:1):0}; will do for a polyfill.