0

I am trying to sort a select option with value and text as follows . The Text can have special characters and it needs to be sorted . However I am finding that , some special characters are coming after alphabets . I want all special characters first and then Alphabets .

c =    [["#test","#test"], ["?test", "?test"], ["test", "test"], ["TEst", "TEst"], ["]test", "]test"]]
    >>> c.sort()
    [["#test", "#test"], ["?test", "?test"], ["TEst", "TEst"], ["]test", "]test"], ["test", "test"]]

The problem seems to be 'TEst' .

Another simple example:

cool = ['#new','?new','[new',']new','NEw','&new','cool','ind']
["#new", "?new", "[new", "]new", "NEw", "&new", "cool", "ind"]
cool.sort()
["#new", "&new", "?new", "NEw", "[new", "]new", "cool", "ind"]

2 Answers 2

2

The issue is specifically with characters with ASCII codes 91-96 and 123-126, which are punctuation or special characters yet have higher codes than the alphabetic characters. So your sort function needs to take that into account.

You could do this, for instance, by mapping those characters onto lower ASCII characters. http://jsfiddle.net/LGjnY/4/

function transformString(s) {
  var r = '',
    code;
  for (var i = 0; i < s.length; i++) {
    code = s.charCodeAt(i);
    // map 91-96 onto 22-27
    if (code >= 91 && code <= 96) code -= 69; 
    // map 123-126 onto 28-31
    else if (code >= 123 && code <= 126) code -= 95; 
    r += String.fromCharCode(code);
  }
  return r;
}
c.sort(function (a, b) {
  return transformString(a[0]).localeCompare(transformString(b[0]));
});

Or combining the comparison and transformation to make it faster (jsfiddle; not really tested)

function compareTransformedStrings(a, b) {
    if (a == b) return 0;
    for (var i = 0, A, B; (A = a.charCodeAt(i)) && (B = b.charCodeAt(i)); i++) {
        if (A != B) {
            return A - (A >= 91 && A <= 96) * 69 - (A >= 123 && A <= 126) * 95
                < B - (B >= 91 && B <= 96) * 69 - (B >= 123 && B <= 126) * 95 
                ? -1 : 1;
        }
    }
    return a.length < b.length ? -1 : 1;
}
c.sort(function (a, b) {
    return compareTransformedStrings(a[0], b[0]);
});
Sign up to request clarification or add additional context in comments.

Comments

2

You can pass a comparison function as a .sort() function argument, like

c.sort(function(a, b) {
    if (a.charCodeAt(0) <= 49) {
        return -1;
    }

    return a.localeCompare(b);
})

Demo: http://jsfiddle.net/7DUEg/

4 Comments

In the example this doesn't differ at all from the default sort. And I guess when a and b are both below ASCII 49 the sort order will be indeterminate?
@Stuart: obviously I gave OP an idea how to improve his code to achieve the desired result. It's up to OP to change the comparison function to fit all the requirements.
Fair enough, just wanted to check I wasn't misunderstanding something about your code.
Yes , it gives the default result . Thanks for the idea .

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.