Rectangle 27 1

How to sort strings in JavaScript?


11.9.6   The Strict Equality Comparison Algorithm

The comparison x === y, where x and y are values, produces true or false. 
Such a comparison is performed as follows: 
- If Type(x) is different from Type(y), return false.
- If Type(x) is Undefined, return true.
- If Type(x) is Null, return true.
- If Type(x) is Number, then
...
- If Type(x) is String, then return true if x and y are exactly the 
  same sequence of characters (same length and same characters in 
  corresponding positions); otherwise, return false.
15.5.4.9   String.prototype.localeCompare (that)
    ...
    The actual return values are implementation-defined to permit implementers 
    to encode additional information in the value, but the function is required 
    to define a total ordering on all Strings and to return 0 when comparing
    Strings that are considered canonically equivalent by the Unicode standard.
NOTE 4     
  Comparison of Strings uses a simple equality test on sequences of code 
  unit values. There is no attempt to use the more complex, semantically oriented
  definitions of character or string equality and collating order defined in the 
  Unicode specification. Therefore Strings values that are canonically equal
  according to the Unicode standard could test as unequal. In effect this 
  algorithm assumes that both Strings are already in normalized form.
Section 11.9.4   The Strict Equals Operator ( === )

The production EqualityExpression : EqualityExpression === RelationalExpression
is evaluated as follows: 
- Let lref be the result of evaluating EqualityExpression.
- Let lval be GetValue(lref).
- Let rref be the result of evaluating RelationalExpression.
- Let rval be GetValue(rref).
- Return the result of performing the strict equality comparison 
  rval === lval. (See 11.9.6)

The triple equals operator applied to strings returns true iff the arguments are exactly the same strings (same length and same characters in corresponding positions).

But there's more. Just above 11.9.4, there is a short note:

Hmm. What now? Externally obtained strings can, and most likely will, be weird unicodey, and our gentle === won't do them justice. In comes localeCompare to the rescue:

I had been bothered about this for long, so I finally researched this and give you this long winded reason for why things are the way they are.

So === will work in the cases when we're trying to compare strings which might have arrived from different sources, but which we know will eventually have the same values - a common enough scenario for inline strings in our code. For example, if we have a variable named connection_state, and we wish to know which one of the following states ['connecting', 'connected', 'disconnecting', 'disconnected'] is it in right now, we can directly use the ===.

To compare strings in javascript, use localeCompare; if you know that the strings have no non-ASCII components because they are, for example, internal program constants, then === also works.

We can go home now.

Note
Rectangle 27 1

How to sort strings in JavaScript?


if (item1.attr < item2.attr)
  return -1
if ( item1.attr > item2.attr)
  return 1
return 0
localeCompare()
return item1.attr.localeCompare(item2.attr);

@Shog9 my bad, it seems like it's supported since IE6! see (scroll-down/search to localeCompare() method) on msdn.microsoft.com/en-us/library/ie/s4esdbwz(v=vs.94).aspx . One thing to note though, In the old implementations where we do not use the locales and options arguments (the one used before IE11) the locale and sort order used are entirely implementation dependent, in other word: Firefox, Safari, Chrome & IE do NOT sort strings in the same order. see code.google.com/p/v8/issues/detail?id=459

Before anyone makes the same hasty mistake as I did, it's localeCompare, not localCompare.

Even better, you can use String.prototype.localeCompare:

No, I mean the first line of the table, @Adrien - IE supports localeCompare() going back many versions, but does not support specifying the locale until version 11. Note also the questions that Dead.Rabit linked to.

The first solution will consider "A" to come after "z" but before "Z" as it's doing a comparison on the character ASCII value. localeCompare() doesn't run into this problem but doesn't understand numerics so you'll get [ "1", "10", "2" ] as with sorting comparisons in most languages. if you want sorting for your UI front end, look into the alphanum/natural sort algorithm stackoverflow.com/questions/4340227/ or stackoverflow.com/questions/4321829/

Note
Rectangle 27 1

How to sort strings in JavaScript?


Alphanum
Javascript Natural Sort
Natural Compare Lite
Natural Sort
Shog9
localeCompare()
return item1.attr.localeCompare(item2.attr);
  • http://jsbin.com/beboroyifomu/2/edit?js,console - basic latin characters in string comparison : consistency check in string vs when a character is alone
  • some will be between the uppercase 'Z' and the lowercase 'a'

I was really annoyed about this string natural sorting order so I took quite some time to investigate this issue. I hope this helps.

My conclusion is that they all fail to provide a consistent order when I start adding barely unusual characters (ie. characters with diacritics or charcters such as dash, exclamation mark and so on).

Research on the browser-native implementations:

Research on the custom implementations:

So considering the current level of support provided by the javascript custom implementations I came across, we will probably never see anything getting any close to supporting all this characters & scripts (languages). Hence I would rather use the browsers' native localeCompare() method. Yes, it does have the downside of beeing non-consistent across browsers but basic testing shows it covers a much wider range of characters, allowing solid & meaningful sort orders.

Thanks to Shog9's nice answer, which put me in the "right" direction I believe

There are quite a bunch of custom implementations out there, trying to do string comparison more precisely called "natural string sort order"

Typically, special characters (space, dash, ampersand, brackets, and so on) are not processed correctly.

When "playing" with these implementations, I always noticed some strange "natural sorting order" choice, or rather mistakes (or omissions in the best cases).

When one would have expected special characters to all be "grouped" together in one place, except for the space special character maybe (which would always be the first character). That is, either all before numbers, or all between numbers and letters (lowercase & uppercase being "together" one after another), or all after letters.

You will then find them appearing mixed up in different places, typically that could be:

localeCompare() character support is badass, just use it. As pointed out by Shog9, the answer to your question is:

Note
Rectangle 27 1

How to sort strings in JavaScript?


list.sort(function(item1, item2) {
    var val1 = item1.attr,
        val2 = item2.attr;
    if (val1 == val2) return 0;
    if (val1 > val2) return 1;
    if (val1 < val2) return -1;
});

On a side note, this won't handle string vs number comparisons. For example: 'Z' < 9 (false), 'Z' > 9 (also false??), 'Z' == 9 (also false!!). Silly NaN in JavaScript...

You should use > or < and == here. So the solution would be:

Note
Rectangle 27 1

How to sort strings in JavaScript?


list.sort((a, b) => (a.attr > b.attr) - (a.attr < b.attr))
list.sort((a, b) => +(a.attr > b.attr) || -(a.attr < b.attr))

Simplest Answer with ECMAScript 2016

Note