Tengo un desafío en JavaScript que ya estoy tratando de resolver por un tiempo.
Considere esta matriz:
let arr = [0, 1, 0, 2, 0, 3, 0, 4, 0, 5];
Tengo que dar salida a este resultado:
arr = [0, 0, 0, 0, 0, 5, 4, 3, 2, 1]
Estoy siguiendo esta línea de lógica para colocar los ceros al frente, ajustando el valor del índice:
arr.sort((x, y) => {
if (x !== 0) {
return 1;
}
if (x === 0) {
return -1;
}
return y - x;
});
Pero estoy atrapado en este resultado:
arr = [0, 0, 0, 0, 0, 1, 2, 3, 4, 5]
¿Alguien tiene algún consejo sobre cómo resolver esto?
javascript
arrays
sorting
lianbwl
fuente
fuente
return x - y;
?return y - x;
? Incluso en javascript, no puedo pensar en nada que no sea ni===0
ni!==0
.Respuestas:
Puede ordenar por el delta de
b
ya
(para la ordenación descendente) y tomarNumber.MAX_VALUE
, para valores falsos como cero.Esta:
es igual a cero
fuente
NaN
si ambosa
yb
son cero. Esto puede ser un comportamiento no deseado.Array.prototype.sort
están definidos por la implementación si el comparador alguna vez regresaNaN
, por lo que este comparador es una mala idea. Intenta ser inteligente y se equivoca.Como dice mdn docs:
Si ayb son dos elementos que se comparan, entonces:
Entonces, la función de comparación tiene la siguiente forma:
fuente
Si le importa la eficiencia, probablemente sea más rápido filtrar los ceros primero . No quiere
sort
perder el tiempo ni siquiera mirándolos, y mucho menos agregando trabajo adicional a su devolución de llamada de comparación para manejar ese caso especial.Especialmente si espera un número significativo de ceros, una pasada sobre los datos para filtrarlos debería ser mucho mejor que hacer una clasificación O (N log N) más grande que analizará cada cero varias veces.
Puede anteponer eficientemente el número correcto de ceros una vez que haya terminado.
También es igual de fácil leer el código resultante. Utilicé TypedArray porque es eficiente y facilita la clasificación numérica . Pero puede usar esta técnica con Array regular, usando el idioma estándar de
(a,b)=>a-b
for.sort
.No sé si TypedArray
.sort()
y luego.reverse
es más rápido que usar una función de comparación personalizada para ordenar en orden descendente. O si podemos copiar y revertir sobre la marcha con un iterador.También vale la pena considerarlo: solo use un TypedArray de longitud completa .
En lugar de usar
.filter
, repítelo y cambia los ceros al frente de la matriz a medida que avanzas. Esto toma una pasada sobre sus datos.Luego, use
.subarray()
para obtener una nueva vista TypedArray de los elementos distintos de cero del mismo ArrayBuffer subyacente. Clasificación que le dejará la matriz completa con un inicio cero y una cola ordenada, con la clasificación solo mirando los elementos que no son cero.No vi una función de partición en los métodos Array o TypedArray, pero apenas conozco JavaScript. Con un buen JIT, un bucle no debería ser mucho peor que un método incorporado. (Especialmente cuando ese método implica una devolución de llamada como
.filter
, y a menos que se utilicerealloc
debajo del capó para reducir, tiene que averiguar cuánta memoria asignar antes de que realmente se filtre).Usé Array regular
.filter()
antes de convertir a un TypedArray. Si su entrada ya es un TypedArray, no tiene este problema, y esta estrategia se vuelve aún más atractiva.fuente
Simplemente modifique la condición de su función de comparación de esta manera:
fuente
!a
sigue siendo cierta. Volverá-1
a=b=0
No estoy jugando código de golf aquí:
fuente
No escriba su propia ordenación numérica si ya existe. Lo que quieres hacer es exactamente lo que dices en el título; ordenar los números en orden descendente, excepto los ceros al comienzo.
No escriba ningún código que no necesite; podrías equivocarte.
Elija el TypedArray según el tipo de números que desea que maneje el arreglo . Float64 es un buen valor predeterminado ya que maneja todos los números JS normales.
fuente
Array(n).fill(0)
.let f64arr = new Float64Array(arr.filter(n => n != 0))
, entonces[ ...Array(arr.length - f64arr.length).fill(0),
... entonces agrega 1 línea extra y simplifica la última línea.Puedes hacer esto así:
o puedes hacer esto:
fuente
fuente