Sorting a mixed array of numbers and strings

Hi there!

I had a recent interview question which stumped me:

Q. The following array is a mix of numbers and strings. Sort the array ascending.

// Original Array:
[1, 'ss', 11, 2, 'aa']
// Expected Output: 
[1, 2, 11, 'aa', 'ss]

I can use the built-in sort function:
[1, 'ss', 11, 2, 'aa'].sort()
But the result is incorrect since 2 should be before 11:
[ 1, 11, 2, 'aa', 'ss' ]

So, I can use a helper function with sort(), but the output is still incorrect:

let myarr = [1, 'ss', 11, 2, 'aa'];
function compareNumbers(a, b) {
  return a - b;
}
myarr.sort(compareNumbers);
console.log(myarr);  // returns [ 1, 'ss', 2, 11, 'aa' ]

Is there an elegant way in JavaScript to sort this array?

Thanks in advance!

Always start with code that works and then look for something elegant.

You callback needs to cover 3 cases, right?

  1. string vs string
  2. string vs number
  3. number vs number

What should happen in each case?

3 Likes

Hi @VayaBuzz !

The best way to approach this is to think about how you would solve it as a human.
As a human, you could sort a list of numbers, then a list of letters and combine the two results into one list.

Then you try to translate that into code.

As mentioned, try to focus on a working solution then think about refactoring.

3 Likes

@JeremyLT and @jwilkins.oboe , thank you so much for the quick responses!
I apologize for my late reply, but I really appreciate your advice!

Your advice harkens back to good 'ol CS fundamentals which I should not forget-- break things down into smaller problems!

This code seemed to work for me, although it may not be super elegant!

// problem:  Sort this array:
let myarr1 = [1, 'ss', 11, 2, 'aa'];
//           expected output:
//           [ 1, 2, 11, 'aa', 'ss' ]
// extra test cases if you need them:
//let myarr2 = ['zzz', 1, 's', 11, 2, 'a', 111];
// solution:
function compareNumbers(a, b) {
  //console.log('a: ' + a);
  //console.log('b: ' + b);
  //console.log('-------');
  if (typeof a === 'number' && typeof b === 'number') {
    return a - b;
  }
  // check for num vs string
  if (typeof a === 'number' && typeof b === 'string') {
    return -1;
  }
  // check for string vs num
  if (typeof a === 'string' && typeof b === 'number') {
    return 1;
  }
  // check for string vs string
  if (typeof a === 'string' && typeof b === 'string') {
    if (a < b) return -1;
    else return 1;
  }
  return 0;
}
myarr1.sort(compareNumbers);
console.log(myarr1);

Again, thanks everyone for your help! I appreciate you greatly!

2 Likes

Cool :slight_smile:
Glad you were able to get it working.

Here was my take on it but I am sure there are millions ways to do this :slight_smile:

let myArr1 = [1, "ss", 11, 2, "aa"];
let myArr2 = ["zzz", 1, "s", 11, 2, "a", 111];
let myArr3 = [56, "awesome", 240, "happy", 6, 89];

function sortArr(arr) {
  let numArr = arr.filter((el) => typeof el === "number").sort((a, b) => a - b);
  let strArr = arr.filter((el) => typeof el === "string").sort();
  return numArr.concat(strArr);
}

console.log(`Unsorted: ${myArr1} Sorted: ${sortArr(myArr1)}`);
console.log(`Unsorted: ${myArr2} Sorted: ${sortArr(myArr2)}`);
console.log(`Unsorted: ${myArr3} Sorted: ${sortArr(myArr3)}`);

3 Likes

What do those return statements do when you check for num vs string, string vs num and string vs string?

I tried a couple approaches. First I went with splitting the list as well, but then I wanted to try a helper function.

This is what I came out with:

const helper = (a, b) => ({
  'numbernumber': a-b,
  'stringnumber': 1,
  'numberstring': -1,
  'stringstring': a > b ? 1 : -1
}[typeof(a) + typeof(b)]);


a = ['b', 2, 'c', 'a', 1, 3, 'hello', 1009];
a.sort(helper);
console.log(a);
1 Like

@Montin the return statements are following the guidelines of a custom compare function.

function compare(a, b) {
  if (a is less than b by some ordering criterion) {
    return -1;
  }
  if (a is greater than b by the ordering criterion) {
    return 1;
  }
  // a must be equal to b
  return 0;
}

See this site for complete info on how how to write your own comparison function:

Array.sort() uses a default comparison function, but if it doesn’t work the way you like, you can write your own comparison function as we did here, and pass the custom comparison function as a parameter to Array.sort().

Cheers,
Patrick

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.