 # How does this .sort / 2D array demo work?

This code block breaks down the order of the .sort operation, but could someone walk me through how this is accomplished line by line?

``````let arr = [90, 1, 20, 14, 3, 55];
var sortRes = [];
var copy = arr.slice();
var inc = 0;
copy.sort((a, b) => {
sortRes[inc] = [a, b, a - b];
inc += 1;
return a - b;
});

var p = 0;
for (var i = 0; i < inc; i++) {
copy = arr.slice();
copy.sort((a, b) => {
p += 1;
if (p <= i) {
return a - b;
} else {
return false;
}
});
p = 0;
console.log(
copy +
" \t a: " +
sortRes[i] +
" \tb: " +
sortRes[i] +
"\tTotal: " +
sortRes[i]
);
}

``````

First, I’m not sure if this example is actually “the best” example to explain the order of how the `sort` function works. I guess it depends on which part you want to understand. If you just want to use it with its comparative function there are other examples that are more straight forward. However, if your curious as to how it works under the hood then it this example might suffice. Its worth keeping in mind it might be easier to build your own sort function from scratch instead.

Also I formatted your code for readability and fixed 1 issue with it (no `}` brace at the end). I also duplicated it in a codepen so anyone can play around with it, to follow along.

Before getting started its worth providing some other links to some parts of the code that might be useful for parts of the code that might trip up someone learning beyond the core syntax:

``````let arr = [90, 1, 20, 14, 3, 55];
var sortRes = [];
var copy = arr.slice();
var inc = 0;
``````
• `arr` is the original starting array.
• `sortRes` is an array we later use with `inc` to keep track of the changes `sort` applies.
• `copy` is a shallow copy of the array created using `slice`. The `sort` applied later to `copy` sorts the array in place, as we later use `arr` and don’t want it sorted, the `copy` is created so we don’t mess up the original.
• `inc` is a simple counter used to keep track of calls to the callback passed to the `sort` we will go into next.
``````copy.sort((a, b) => {
sortRes[inc] = [a, b, a - b];
inc += 1;
return a - b;
});
``````

This is the first `.sort` call that actually does multiple things beyond just sorting.

`sortRes[inc] = [a, b, a - b];` updates the index `inc` with an array of multiple values at the same time. Another way to think of the `[a, b, a - b]` is actually whats called a tuple, which is similar to an array which can be thought of as a “finite group of elements”. JS doesn’t directly have a tuple, rather its just an array with finite values, with the only difference in how your using it.
Quickly going into the tuple, `a` and `b` are the 2 numbers being compared, and the result of `a - b` is also saved to keep track of how its sorted.

``````inc += 1;
return a - b;
``````

going over the other 2 lines of the first `sort` callback updates the increment, so we can see each call of the `sort` and the `a - b` is the actual logic that the `sort` cares about. As mentioned in the docs:

``````
If compareFunction(a, b) returns less than 0, sort a to an index lower than b (i.e. a comes first).
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAScript standard only started guaranteeing this behavior in 2019, thus, older browsers may not respect this.
If compareFunction(a, b) returns greater than 0, sort b to an index lower than a (i.e. b comes first).
compareFunction(a, b) must always return the same value when given a specific pair of elements a and b as its two arguments. If inconsistent results are returned, then the sort order is undefined.
``````

So essentially the `return a - b` line is telling `sort` to sort from the smallest integer to the largest.

Now onto the next for loop, there’s actually some code in this part that doesn’t do anything, which I point out

``````var p = 0;
for (var i = 0; i < inc; i++) {
copy = arr.slice();
copy.sort((a, b) => {
p += 1;
if (p <= i) {
return a - b;
} else {
return false;
}
});
//...other code
}
``````

(I cut out the console log for now)

``````var p = 0;
for (var i = 0; i < inc; i++) {
copy = arr.slice();
``````
• `var p = 0` is another counter used iterate against `i`.
• `for (var i = 0; i < inc; i++) {` this for loop iterates over all the `inc` we made earlier using `i` as its “counter”. Everything inside of this `for` loop is more or less done in relation to `i` which is “counting” to the number of `inc` we did earlier.
• `copy = arr.slice();` makes another shallow copy of the original `arr` and `copy`
`````` copy.sort((a, b) => {
p += 1;
if (p <= i) {
return a - b;
} else {
return false;
}
});
p = 0;
// console log
``````

So here is the “fun” part, which IMO is the most confusing part of the entire code.

• ` copy.sort((a, b) => {` we start another “sort” of our new shallow copy of the `copy` array.
• `p += 1` increments the `p` counter again, keeping track of which iteration of the `sort` we are going thru for the given iteration as defined by`i` from the `for` loop. So for every `i` we sort the `copy` and for each call to `sort` we update the `p` counter.

finally this chunk:

``````if (p <= i) {
return a - b;
} else {
return false;
}
``````

(mind you this is where I’m actually not 100% sure I know whats going on, as it depends on the behavior of returning `false` from the callback passed to `sort`)

essentially this block executes the same logic as the first `sort` until `p` is greater than or less than `i` (which if you remember is counting to `inc`). So it kinda just “throws away” executions with `false` which I believe is calculated to be `0` and thus doesn’t change the order of these 2 functions. I believe the purpose of this is print out the “execution” status of the `arr`, as once `p <= i` the sorting essentially “stops” allowing the `console` log to be shown later.

after executing `sort` the code resets `p = 0` and moves onto the next iteration of `sort`.

And finally `console.log` prints out the steps up until that point.

So to abstract what this code is doing it does:

1. sort the array and keep track of what its sorting
2. iterate over the previous sorts to print out what each `sort` call is doing.

The reason why this breakdown is done “kinda confusing” is the fact the first `sort` call is somewhat of a “black box” in that if you want to see what the `copy` is at a given time you can’t until `sort` was already ran.

So hopefully that extensive breakdown helps ;D I had a good amount of free time go over the code and the code seemed interesting enough to really dive into it.

Keep learning, keep building 1 Like

Damn! That was thorough! Thanks, man. I think I understand it now. The parts that had me looking askance at this code were the need for 2 .slices(). Why did we need to create two “shallow” copies. And other one was the relationship between “p” the “i” and “inc”. But yeah, once again, thanks for taking the time to explain all of this!

1 Like

I do have one lingering question - why does the “p” need to be reset each time the for loop runs, and why does not resetting it cause the sort not to work?

The `p` is essentially used to “count” back up to where `i` is. This isn’t done by a loop but rather the 2nd `sort`, which makes it kinda off. So after `p` gets to `i` the sort stops sorting. To prepare for the next iteration via the `for` loop using `i` `p` is reset so sort can count back up to `i` via sort.

1 Like

So I did a console log on p and i, and it does look like p has to catch up to where i is during each loop iteration, so, for example, at the 4th iteration - the console.log(‘p’ + p, ‘i’ + i) looks like this p:1, i:4, p:2, i:4, p:3, i:4, p:4, i:4. Does this mean that the sort is sorting 4 times in that particular instance? And if so, is it retracing the sorts that it already did from the three previous sorts?