0

I'm attempting to create my own sort function (question Async version of sort function in JavaScript). I've taken merge sort function from Rosetta Code and make it async:

// based on: https://rosettacode.org/wiki/Sorting_algorithms/Merge_sort#JavaScript
async function mergeSort(fn, array) {
    if (array.length <= 1) {
        return array;
    }
    const mid = Math.floor(array.length / 2),
          left = array.slice(0, mid), right = array.slice(mid);
    await mergeSort(fn, left)
    await mergeSort(fn, right)
    let ia = 0, il = 0, ir = 0;
    while (il < left.length && ir < right.length) {
        array[ia++] = (await fn(left[il], right[ir]) <= 0) ? left[il++] : right[ir++];
    }
    while (il < left.length) {
        array[ia++] = left[il++];
    }
    while (ir < right.length) {
        array[ia++] = right[ir++];
    }
    return array;
}

But I'm not sure how I can define default function fn to work the same as in JavaScript.

console.log([1, 2, 3, 10, 11, 100, 20].sort());

What should be the default sorting function to match those in the JavaScript engine? Should I convert numbers to strings and compare those? What is the proper implementation?

6
  • 2
    Did you read e.g. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…? Commented May 24, 2022 at 17:52
  • @jonrsharpe yes, there is an example of a.localeCompare(b); but this is not the default behavior of a sort function. Commented May 24, 2022 at 17:54
  • 1
    ...it describes the default behaviour, without a compare function. See also tc39.es/ecma262/#sec-array.prototype.sort. Commented May 24, 2022 at 17:55
  • So the background of the async sorting is irrelevant to the question? Is this really just asking "what would be the callback passed to sort to get the default behaviour?" Commented May 24, 2022 at 18:02
  • @jonrsharpe thanks I think I get it, I'll add an answer with my function. Commented May 24, 2022 at 18:10

3 Answers 3

1

Updated Answer

The default sort method as defined in core.js looks like so

var getSortCompare = function (comparefn) {
  return function (x, y) {
    if (y === undefined) return -1;
    if (x === undefined) return 1;
    if (comparefn !== undefined) return +comparefn(x, y) || 0;
    return toString(x) > toString(y) ? 1 : -1;
  };

Taken from this repo: https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.sort.js

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

5 Comments

Ok, but the question is what compare should look like if not defined. If you look at my code it's exactly the same, only variable names are different.
Just add a default value for the parameter, I'll update the answer.
This is not a proper compare function, because it will work as expected sporting numbers in order, which is not how JavaScript sorting works. JavaScript sorts method sorts numbers alphabetically.
@jcubic here is the link to the source code: github.com/zloirock/core-js/blob/master/packages/core-js/…
Thanks, now it looks like a proper answer.
0

Based on @jonrsharpe comments I was able to implement proper default function:

function defaultSortFn(a, b) {
    if (typeof a !== 'string') {
        a = String(a);
    }
    if (typeof b !== 'string') {
        b = String(b);
    }
    if (a < b) {
        return -1;
    }
    if (a > b) {
        return 1;
    }
    return 0;
}

that can be used in my sort:

Array.prototype.sort = function(fn = defaultSortFn) {
   return mergeSort(fn, this);
};

Comments

0

The ECMAScript specification for Arra.prototype.sort mentions that the comparison (in absence of a comparator) involves:

e. Let xString be ? ToString(x).
f. Let yString be ? ToString(y).
g. Let xSmaller be ! IsLessThan(xString, yString, true).
h. If xSmaller is true, return -1𝔽.
i. Let ySmaller be ! IsLessThan(yString, xString, true).
j. If ySmaller is true, return 1𝔽.
k. Return +0𝔽.

Given that the IsLessThan procedure is also executed when two strings are compared with the < operator, we can faithfully replicate the default callback function as follows:

function (x, y) {
    let xString = String(x);
    let yString = String(y);
    return xString < yString ? -1 : yString < xString ? 1 : 0;
}

Comments

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.