Quiero ordenar esta matriz de objetos donde cada objeto debe ascender en cada unit
y las unidades también deben ordenarse de manera ascendente según el order
:
const userCards = [ { unit: 5, order: 1, }, { unit: 5, order: 3, }, { unit: 5, order: 2, }, { unit: 6, order: 2, }, { unit: 6, order: 1, }, { unit: 6, order: 3, }, { unit: 7, order: 1, }, { unit: 4, order: 2, }, { unit: 1, order: 1, }, { unit: 1, order: 2, }, { unit: 1, order: 3, }, { unit: 1, order: 4, }, { unit: 3, order: 2, } ] function compare(a, b) { if (a.unit > b.unit && a.order > b.order) return 1; if (a.unit < b.unit) return -1; return 0; } const res = userCards.sort(compare); console.log(res)
Por ejemplo, el resultado deseado sería:
{ unit: 5, order: 1, }, { unit: 5, order: 2, }, { unit: 6, order: 1, }, { unit: 6, order: 2, },
Como ves hasta ahora esto no está pasando!
¿Cómo puedo arreglar esto?
function compare(a, b) { if (a.unit == b.unit) { return a.order - b.order; } return a.unit - b.unit; }
Los detalles se comentan en el ejemplo a continuación.
const userCards = [{ unit: 5, order: 1, }, { unit: 5, order: 2, }, { unit: 6, order: 2, }, { unit: 6, order: 1, }, { unit: 6, order: 3, }, { unit: 7, order: 1, }, { unit: 5, order: 3, }, { unit: 4, order: 2, }, { unit: 1, order: 1, }, { unit: 1, order: 2, }, { unit: 1, order: 3, }, { unit: 1, order: 4, }, { unit: 3, order: 2, } ]; /* Create a reference object array that stores the keys needed to be in order */ let orderKey = [{ key: 'unit' }, { key: 'order' }]; // Pass both object arrays function compare(objArray, sortOrder) { // Start with .sort() return objArray.sort((a, b) => { // Define counter and ternary value initial defaults let i = 0, result = 0; /* As long as counter is less than sortOrder total AND ternary is 0 ...Define A as previous value of current key... ...Define B as current value of current key... ...If A is less than B return -1 (A and B stay)... ...if A is greater than B return 1 (A and B swap)... ...else return 0 (A and B stay)... ...increment counter... */ while (i < sortOrder.length && result === 0) { let A = a[sortOrder[i].key], B = b[sortOrder[i].key]; result = A < B ? -1 : A > B ? 1 : 0; i++; } return result; }); } console.log(JSON.stringify(compare(userCards, orderKey)));
A | B | a.unidad > b.unidad && a.orden > b.orden | a.unidad > b.unidad | valor devuelto |
---|---|---|---|---|
{unidad: 5, pedido: 3} | {unidad: 4, pedido: 1} | Verdadero | 1 <-- significa A > B | |
{unidad: 5, pedido: 3} | {unidad: 5, pedido: 1} | Falso | Falso | 0 <-- significa el mismo valor |
{unidad: 4, pedido: 1} | {unidad: 3, pedido: 2} | Falso | Verdadero | -1 <-- significa A > B |
{unidad: 1, pedido: 1} | {unidad: 3, pedido: 2} | Falso | Verdadero | 0 <-- significa el mismo valor |
Como puede ver en este ejemplo, su condición no funciona como desea ya que ha regresado 0
2 veces.
Al leer la documentación de Array#sort , el retorno de la función de clasificación es el siguiente
compareFunction(a, b) valor de retorno | Orden de clasificación |
---|---|
> 0 | ordenar b antes de a |
< 0 | ordenar a antes de b |
=== 0 | mantener el orden original de a y b |
Así que aquí puedes hacer lo siguiente:
function compare(a, b) { if(a.unit === b.unit) return a.order - b.order else return a.unit - b.unit }
O con una línea usando ternario
function compare = (a, b) => a.unit === b.unit ? a.order - b.order : a.unit - b.unit
const userCards = [ { unit: 5, order: 1, }, { unit: 5, order: 3, }, { unit: 5, order: 2, }, { unit: 6, order: 2, }, { unit: 6, order: 1, }, { unit: 6, order: 3, }, { unit: 7, order: 1, }, { unit: 4, order: 2, }, { unit: 1, order: 1, }, { unit: 1, order: 2, }, { unit: 1, order: 3, }, { unit: 1, order: 4, }, { unit: 3, order: 2, } ] const compare = (a, b) => a.unit === b.unit ? a.order - b.order : a.unit - b.unit const res = userCards.sort(compare); console.log(JSON.stringify(res))