2

I have an array of strings in JavaScript:

var nick = ["~xxx", "@blue", "&demo", "+voice", "%yyy",
    "nick1", "Nick2", "webmaster"];

I want to sort those strings so the result is in this order:

~xxx &demo @blue %yyy +voice nick1 Nick2 webmaster

How can I do it?

1

2 Answers 2

1

This is a bit trickier that it may seem at first. But here is one way to do it, assuming the special characters listed are the only ones you're concerned with:

var separator = '\uFFFF';

var prefixes = {
    '~': '1',
    '&': '2',
    '@': '3',
    '%': '4',
    '+': '5'
};

function specialsort( array ) {
    var prefixed = array.map( function( value ) {
        var prefix = prefixes[ value.charAt(0) ] || '9';
        return prefix +
            value.toLowerCase() +
            separator + value;
    });
    prefixed.sort();
    return prefixed.map( function( value ) {
        return value.split(separator)[1];
    });
}

var nicks = [ "~xxx", "@blue", "&demo", "+voice", "%yyy", "nick1", "Nick2", "webmaster" ];

var sorted = specialsort( nicks );
console.log( sorted );

The code works by creating a new array with strings formatted like this:

  1. The first character is a digit 1-5 for the special characters or 9 for any other character found at the beginning of each string. (You could extend this to two digits using '01', '02', etc. and '99' for other characters.)
  2. Next is the string in lowercase.
  3. Then a Unicode character with a very large value (\uFFFF) as a separator.
  4. Finally, the original string.

The array of these strings can then be sorted directly, and the result is converted to a new array by splitting the strings on that separator and using the part after the separator (the original string).

Or, a slightly simpler approach using a sort callback function:

var prefixes = {
    '~': '1',
    '&': '2',
    '@': '3',
    '%': '4',
    '+': '5'
};

function specialsort( array ) {
    return array.sort( function( a, b ) {
        a = ( prefixes[ a.charAt(0) ] || '9' ) + a.toLowerCase();
        b = ( prefixes[ b.charAt(0) ] || '9' ) + b.toLowerCase();
        return a < b ? -1 : a > b ? 1 : 0;
    });
}

var nicks = [ "~xxx", "@blue", "&demo", "+voice", "%yyy", "nick1", "Nick2", "webmaster" ];

var sorted = specialsort( nicks );
console.log( sorted );

For lengthy arrays, I tend to go for the first approach—making a modified array and sorting it—because it can be faster than using a sort callback. But the sort callback is a bit simpler and there's nothing wrong with it for an array of this size.

The sort callback approach does have one other advantage over the modified array: it doesn't depend on that slightly hacky separator character.

Either way, the output is:

["~xxx", "&demo", "@blue", "%yyy", "+voice", "nick1", "Nick2", "webmaster"]

Here's a fiddle for the first version and a fiddle for the second version.

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

Comments

0

You can use regular expression and localeCompare() function, for case insensitive comparation add two lowercases:

var nick = ["~xxx", "@blue", "&demo", "+voice", "%yyy", "nick1", "Nick2", "webmaster"];
nick.sort(function(a,b){
    return a.toLowerCase().replace(/[^\w\s]/gi, '').localeCompare(b.toLowerCase().replace(/[^\w\s]/gi, ''));
});
console.log(nick); // ["@blue", "&demo", "nick1", "Nick2", "+voice", "webmaster", "~xxx", "%yyy"]

http://jsfiddle.net/4JJVV/

2 Comments

Is your console.log output in the same order the OP requested?
This code sorts the array alphabetically, just those leading special characters are ignored while sorting.

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.