0

I have to write a function, which sorts an array containing numbers and strings.
For example:

uSort([3,"2", 4,1,"a","c","b"])  // -> ["a","b","c",1,"2",3, 4].

This is what I've tried so far:

function uSort(arrayOfChars){
    var array = [];
    for (i = 0; i < arrayOfChars.length; i++) { 
        if (typeof(arrayOfChars[i]) === '' ){ 
            array.unshift(arrayOfChars[i]); }
        else { 
            array.push(arrayOfChars[i]);
        };   
    }; 
    return array.sort();
};

But the result is wrong:

uSort([3,"2", 4,1,"a","c","b"])  // -> [1,"2",3, 4,"a","b","c"].

I can't figure out what is wrong with my code right now.

6
  • So strings before numbers ? Commented Oct 11, 2015 at 13:21
  • That's right adeneo. Commented Oct 11, 2015 at 13:23
  • typeof will never return ''. Commented Oct 11, 2015 at 13:25
  • You should not be unsifting an array you are sorting, moving them to the end will make ZERO difference when you sort after it. Commented Oct 11, 2015 at 13:27
  • 1
    You need to write your own custom sort method. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Oct 11, 2015 at 13:29

4 Answers 4

3

One easy way to do that would be to just split the array into two arrays, one containing numbers and strings that are numbers, using isNaN, and one array containing everything else, then sort them and join them back together

function uSort(arrayOfChars){
    var numbs = arrayOfChars.filter(function(item) { return isNaN(item) });
    var chars = arrayOfChars.filter(function(item) { return !isNaN(item) });

    return numbs.sort().concat( chars.sort() );
};

FIDDLE

For better sorting of integers and special characters, you can add callbacks to the sorting

function uSort(arrayOfChars){
    var numbs = arrayOfChars.filter(function(item) { return !isNaN(item) });
    var chars = arrayOfChars.filter(function(item) { return isNaN(item) });

    return chars.sort(function(a, b) {
        return a.localeCompare(b);
    }).concat( numbs.sort(function(a, b) {
        return a == b ? 1 : a - b;
    }));
};

FIDDLE

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

6 Comments

You will still have to implement better number sorting, add a 10 anywhere and it will look like this ["a", "b", "c", 1, 10, "2", 3, 4]
The string digits should be after the number ["a","b","c",1,"1",2,"2","2",3,"3"], instead got: ["a","b","c","1",1,"2",2,"2",3,"3"]
Seems weird you would do all of that when one sort method with a couple of checks works just as well.
@epascarello - at least it doesn't return ["a", "c", "b", ...] like yours ?
@Dennis - modified the last one to do that as well.
|
1

You can use a custom comparator function which checks if the arguments are numeric with isNaN and then uses numerical or lexicographic sort:

[3, "2", 4, 1, "a", "c", "b"].sort(function(a,b) {
  if(isNaN(a) || isNaN(b)) {
    if(!isNaN(a)) return +1;              // Place numbers after strings
    if(!isNaN(b)) return -1;              // Place strings before numbers
    return a < b ? -1 : (a > b ? +1 : 0); // Sort strings lexicographically
  }
  return a - b;                           // Sort numbers numerically
}); // ["a", "b", "c", 1, "2", 3, 4]

Comments

1

Write your own custom sort method.

[3,"2", 4,1,"a","c","b"].sort( function (a,b) { 
    var sa = isNaN(a);
    var sb = isNaN(b);
    if(sa && sb) { //If both are strings, than compare
        return sa>sb; 
    } else if (!sa && !sb) {  //if both are numbers, convert to numbers and compare
        return Number(a) - Number(b);
    } else {  //if we have a number and a string, put the number last.
        return sa ? -1 : 1;
    }
});

2 Comments

also, you don't need to explicitly convert to Number if both are not NaN.
It was supposed to be > @Oriol
0

It's normal to have numbers before letters (if this is your problem).

If you want to have letters before you have different ways.

One way is to order elements into two arrays (one for letters and one for numbers), then to merge them in the order you need.

Another way is to move the numbers at the end.

This is an example: alert((uSort([3,"2", 4,10,"a","c","b"]))) // -> ["a","b","c",1,"2",3, 4].

function uSort(arrayOfChars){
    var arrayNum = [];
    var arrayLet = [];
    for (i = 0; i < arrayOfChars.length; i++) { 
        if (typeof(arrayOfChars[i]) === '' ){ 
            array.unshift(arrayOfChars[i]); }
        else if (typeof(arrayOfChars[i]) === 'number' ){ 
            arrayNum.push(arrayOfChars[i]);
        } else {
            arrayLet.push(arrayOfChars[i]);
        }
    }; 

    if (arrayNum.size!=0 && arrayLet.size!=0) {
        arrayNum = arrayNum.sort(sortNumber);
        arrayNum.push();
        return arrayNum.concat(arrayLet.sort());
    } else if (arrayNum.size!=0) {
        return arrayNum.sort(sortNumber);
    } else {
        return arrayLet.sort();
    }


};

function sortNumber(a,b) {
    return a - b;
}

5 Comments

True, but techically "2" isn't a number so you will have to add type casting as well
Yes, that's why I've used array.unshift to put the numbers at the end, but it still doesn't work.
There is no reason to do that and adding two arrays does not produce an array. That is totally wrong
This doesn't work. In example uSort([3,"2", 4,1, 10,"a","c","b"]) returns 1,10,3,42,a,b,c
it's wrong just the last line (that creates a string)... btw the other is correct... you need just to use concat()

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.