TypeScript ordenando una matriz


154

He estado tratando de resolver un problema muy extraño que encontré con el mecanografiado. Trataba una expresión booleana en línea como el tipo del primer valor en lugar de la expresión completa.

Entonces, si intentas algo simple como lo siguiente:

var numericArray:Array<number> = [2,3,4,1,5,8,11];

var sorrtedArray:Array<number> = numericArray.sort((n1,n2)=> n1 > n2);

Intentalo

Recibirá un error en su método de clasificación que indica que los parámetros no coinciden con ninguna firma del destino de la llamada, porque su resultado es numérico y no booleano. Supongo que me falta algo porque estoy bastante seguro de que n1> n2 es una declaración booleana.

Respuestas:


180

El error es completamente correcto.

Como intenta decirte, .sort()toma una función que devuelve un número, no booleano.

Debe devolver negativo si el primer elemento es más pequeño; positivo si es más grande, o cero si son iguales.


56
¡Por eso usamos TypeScript! :-)
— Stephen Chung

226

Números

Al ordenar números, puede usar la comparación compacta:

var numericArray: number[] = [2, 3, 4, 1, 5, 8, 11];

var sortedArray: number[] = numericArray.sort((n1,n2) => n1 - n2);

es decir, en -lugar de <.

Otros tipos

Si está comparando cualquier otra cosa, deberá convertir la comparación en un número.

var stringArray: string[] = ['AB', 'Z', 'A', 'AC'];

var sortedArray: string[] = stringArray.sort((n1,n2) => {
    if (n1 > n2) {
        return 1;
    }

    if (n1 < n2) {
        return -1;
    }

    return 0;
});

Objetos

Para los objetos, puede ordenarlos en función de una propiedad, tenga en cuenta la información anterior sobre la posibilidad de abreviar los tipos de números. El siguiente ejemplo funciona independientemente del tipo.

var objectArray: { age: number; }[] = [{ age: 10}, { age: 1 }, {age: 5}];

var sortedArray: { age: number; }[] = objectArray.sort((n1,n2) => {
    if (n1.age > n2.age) {
        return 1;
    }

    if (n1.age < n2.age) {
        return -1;
    }

    return 0;
});

¿Podría alguien explicar por qué, para la prueba menor que, 'Roy@my.net' devuelve verdadero por menos de 'bob@my.net'? por ejemplo: let myTest = ('Roy@my.net' <'bob@my.net'); // devuelve cierto para mí ... :(
— Wallace Howery

1
en el segundo caso, puede usar localeCompare () para comparar cadenas en la configuración regional actual, que devuelve un número
— neural5torm

Por favor explícame, ¿Cómo (n1,n2)=>n1-n2se ejecutará o funcionará la expresión?
— Rahul Chaudhari

1
@RahulChaudhari en el ejemplo de número, es una función que toma los números n1y n2, dentro de la función que devuelve n1-n2, que será un número positivo, cero o un número negativo. Esto le dice a la operación de clasificación si los elementos deben cambiarse o no, permitiendo así la clasificación.
— Fenton

es posible filtrar con propiedad diferente
— Arvind

24

Gran respuesta Sohnee. Me gustaría agregar que si tiene una matriz de objetos y desea ordenar por clave, entonces es casi lo mismo, este es un ejemplo de uno que puede ordenar por fecha (número) o título (cadena):

    if (sortBy === 'date') {
        return n1.date - n2.date
    } else {
        if (n1.title > n2.title) {
           return 1;
        }
        if (n1.title < n2.title) {
            return -1;
        }
        return 0;
    }

También podría hacer que los valores en el interior sean variables n1 [campo] vs n2 [campo] si es más dinámico, solo mantenga la diferencia entre cadenas y números.


Los comentarios sobre las respuestas deben hacerse utilizando la función de comentarios.
— Nicktar

66
@Nicktar Probablemente se publique como una respuesta para el formato. Pero de todos modos no hace ningún daño
— Wouter Vanherck

11
let numericArray: number[] = [2, 3, 4, 1, 5, 8, 11];

let sortFn = (n1 , n2) => number { return n1 - n2; }

const sortedArray: number[] = numericArray.sort(sortFn);

Ordenar por algún campo:

let arr:{key:number}[] = [{key : 2}, {key : 3}, {key : 4}, {key : 1}, {key : 5}, {key : 8}, {key : 11}];

let sortFn2 = (obj1 , obj2) => {key:number} { return obj1.key - obj2.key; }

const sortedArray2:{key:number}[] = arr.sort(sortFn2);

1
n1 - n2 es negativo cuando n1 <n2, positivo cuando n1> n2 y 0 cuando n1 == n2
— Sébastien Stormacq

2
¡Gracias! Lo cambié por esto: myArray.sort ((a, b): number => {return a.NumberProp - b.NumberProp;});
— Lrodriguez84

10

Ordenar matriz mixta (alfabetos y números)

function naturalCompare(a, b) {
   var ax = [], bx = [];

   a.replace(/(\d+)|(\D+)/g, function (_, $1, $2) { ax.push([$1 || Infinity, $2 || ""]) });
   b.replace(/(\d+)|(\D+)/g, function (_, $1, $2) { bx.push([$1 || Infinity, $2 || ""]) });

   while (ax.length && bx.length) {
     var an = ax.shift();
     var bn = bx.shift();
     var nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]);
     if (nn) return nn;
   }

   return ax.length - bx.length;
}

let builds = [ 
    { id: 1, name: 'Build 91'}, 
    { id: 2, name: 'Build 32' }, 
    { id: 3, name: 'Build 13' }, 
    { id: 4, name: 'Build 24' },
    { id: 5, name: 'Build 5' },
    { id: 6, name: 'Build 56' }
]

let sortedBuilds = builds.sort((n1, n2) => {
  return naturalCompare(n1.name, n2.name)
})

console.log('Sorted by name property')
console.log(sortedBuilds)


Muchas gracias :)
— Steve


0

function naturalCompare(a, b) {
   var ax = [], bx = [];

   a.replace(/(\d+)|(\D+)/g, function (_, $1, $2) { ax.push([$1 || Infinity, $2 || ""]) });
   b.replace(/(\d+)|(\D+)/g, function (_, $1, $2) { bx.push([$1 || Infinity, $2 || ""]) });

   while (ax.length && bx.length) {
     var an = ax.shift();
     var bn = bx.shift();
     var nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]);
     if (nn) return nn;
   }

   return ax.length - bx.length;
}

let builds = [ 
    { id: 1, name: 'Build 91'}, 
    { id: 2, name: 'Build 32' }, 
    { id: 3, name: 'Build 13' }, 
    { id: 4, name: 'Build 24' },
    { id: 5, name: 'Build 5' },
    { id: 6, name: 'Build 56' }
]

let sortedBuilds = builds.sort((n1, n2) => {
  return naturalCompare(n1.name, n2.name)
})

console.log('Sorted by name property')
console.log(sortedBuilds)


Hola, Bienvenido a stackoverflow, stackoverflow.com/help/how-to-answer , lea esta documentación y proporcione una descripción de lo que debe hacerse.
— Prateik Darji

0

Escribí este hoy mientras trataba de recrear _.sortByen TypeScript, y pensé que lo dejaría para cualquiera que lo necesite.

// ** Credits for getKeyValue at the bottom **
export const getKeyValue = <T extends {}, U extends keyof T>(key: U) => (obj: T) => obj[key] 

export const sortBy = <T extends {}>(index: string, list: T[]): T[] => {
    return list.sort((a, b): number => {
        const _a = getKeyValue<keyof T, T>(index)(a)
        const _b = getKeyValue<keyof T, T>(index)(b)
        if (_a < _b) return -1
        if (_a > _b) return 1
        return 0
    })
}

Uso:

Espera una matriz de tipo genérico T, de ahí la conversión para <T extends {}>, además de escribir el tipo de parámetro y función de retorno conT[]

const x = [{ label: 'anything' }, { label: 'goes'}]
const sorted = sortBy('label', x)

** getByKeyfn encontrado aquí

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.