Estoy intentando crear mi propia función de clasificación (pregunta Versión asincrónica de la función de clasificación en JavaScript ). Tomé la función de clasificación por fusión de Rosetta Code y la hice asíncrona:
// 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; }Pero no estoy seguro de cómo puedo definir la función predeterminada fn para que funcione igual que en JavaScript.
console.log([1, 2, 3, 10, 11, 100, 20].sort());¿Cuál debería ser la función de clasificación predeterminada para que coincida con las del motor de JavaScript? ¿Debo convertir números en cadenas y compararlos? ¿Cuál es la implementación adecuada?
El método de sort predeterminado como se define en core.js parece así
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; };Tomado de este repositorio: https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.sort.js
Según los comentarios de @jonrsharpe, pude implementar la función predeterminada adecuada:
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; }que se puede utilizar en mi tipo:
Array.prototype.sort = function(fn = defaultSortFn) { return mergeSort(fn, this); };La especificación ECMAScript para Arra.prototype.sort menciona que la comparación (en ausencia de un comparador) implica:
mi. Sea xString ? ACadena( x ).
F. Sea yString ? ACadena( y ).
gramo. ¡Que sea xSmaller ! EsMenorQue( xCadena , yCadena , verdadero ).
H. Si xSmaller es verdadero, devuelve -1 𝔽 .
i. ¡Que sea ySmaller ! EsMenorQue( yCadena , xCadena , verdadero ).
j. Si ySmaller es verdadero, devuelve 1 𝔽 .
k. Retorno +0 𝔽 .
Dado que el procedimiento IsLessThan también se ejecuta cuando se comparan dos cadenas con el operador < , podemos replicar fielmente la función de devolución de llamada predeterminada de la siguiente manera:
function (x, y) { let xString = String(x); let yString = String(y); return xString < yString ? -1 : yString < xString ? 1 : 0; }