FCC Bonfire Series 118: Where do I belong

Sorting arrays is something everyone should me familiar with. Todays challenge will have us write a function that takes an array composed of numbers as the first argument, and a single number as the second. The function should return the lowest index at which our second argument should go in that array (in ascending order).

If you are familiar with the Array.prototype.sort() method, a first thought might look like so if combined with indexOf:

function where(arr, num) {
  arr.push(num);
  arr.sort();
  return arr.indexOf(num);
}

This function merely inserts the number in the array, then sorts it using the default sort() method and outputs the first index of the given number. This function will actually work in many cases; but many is not enough, we need it to work every time. Let’s first dig into why it won’t work on some cases.

The sort method, by default, will convert every item in the array to a string and compare them by their Unicode code point order. This will usually work great for strings, but when comparing numbers, some problems arise, here’s a few examples:

var myArray = [10, 14, 1, 2, 7, 80, 20];
console.log(myArray.sort()); //-> [1, 10, 14, 2, 20, 7, 80]

Whoa! What happened there! Actually, the sort method converted every number into a string, and when comparing strings, ‘a’ goes before ‘ab’, but ‘ab’ goes before ‘b’. And this is why number two (2) comes behind ten (10) and fourteen (14) in our comparison.

For our convenience, the sort method accepts an argument, we’ll call it a comparison function. This function should take two variables (those two variables represent every item pair inside the array) and should return a number:

  • A number below 0 means that a should go at an index lower than b (a is lesser than b).
    If the returned number is 0, it means that both items are the same.
    A number greater than 0 means that b should preceed a.

Let’s write our own comparison function:

function compareFunction(a, b) {
  if (a < b) {
    return -1; // a goes before b
  } else if (a > b) {
    return 1; // b goes before a
  } else {
    return 0; // a and b are equal
  }
}

Now we can pass this function (which will compare by numerical value rather than Unicode code code order) into the sort method:

function where(arr, num) {
  arr.push(num);
  arr.sort(compareFunction);
  return arr.indexOf(num);
}

This function should work much better (as long as you include the compare function in your code). We can also directly pass in the function into sort as an anonymous function. Let’s try to shorten our code using this method:

function where(arr, num) {
  arr.push(num);
  return arr.sort(function(a, b) {
    return a < b ? -1 : a > b ? 1 : 0;
  }).indexOf(num);
}

We have turned our compare function into an anonymous function and made use of a nested ternary operator. If you do not fully understand it at first, that’s ok, it can look a bit confusing; just keep trying to implement this methods in your own code, and make it work for you!