TypeScript tri d'un tableau


154

J'ai essayé de comprendre un problème très étrange que j'ai rencontré avec le tapuscrit. Il traitait une expression booléenne en ligne comme quel que soit le type de la première valeur au lieu de l'expression complète.

Donc, si vous essayez quelque chose de simple comme celui-ci:

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

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

TryIt

Vous obtiendrez une erreur sur votre méthode de tri indiquant que les paramètres ne correspondent à aucune signature de la cible de l'appel, car votre résultat est numérique et non booléen. Je suppose que je manque quelque chose car je suis presque sûr que n1> n2 est une instruction booléenne.

Réponses:


180

L'erreur est tout à fait correcte.

Comme il essaie de vous le dire, .sort()prend une fonction qui renvoie un nombre, pas un booléen.

Vous devez renvoyer négatif si le premier élément est plus petit; positive si elle est plus grande, ou zéro si elles sont égales.


56
C'est pourquoi nous utilisons TypeScript! :-)
— Stephen Chung

226

Nombres

Lors du tri des nombres, vous pouvez utiliser la comparaison compacte:

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

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

c'est à dire -plutôt que <.

Autres types

Si vous comparez autre chose, vous devrez convertir la comparaison en un nombre.

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;
});

Objets

Pour les objets, vous pouvez trier en fonction d'une propriété, gardez à l'esprit les informations ci-dessus sur la possibilité de raccourcir les types de nombres. L'exemple ci-dessous fonctionne quel que soit le type.

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;
});

Quelqu'un pourrait-il expliquer pourquoi, pour le test inférieur à, «Roy@my.net» renvoie vrai pour moins que «bob@my.net»? par exemple: let myTest = ('Roy@my.net' <'bob@my.net'); // renvoie vrai pour moi ... :(
— Wallace Howery

1
dans le second cas, vous pouvez utiliser localeCompare () pour comparer des chaînes dans la locale actuelle, qui renvoie un nombre
— neural5torm

Veuillez m'expliquer, comment l' (n1,n2)=>n1-n2expression s'exécutera ou fonctionnera .. ??
— Rahul Chaudhari

1
@RahulChaudhari dans l'exemple de nombre, c'est une fonction qui prend les nombres n1et n2, dans la fonction qu'elle renvoie n1-n2, qui sera soit un nombre positif, zéro ou un nombre négatif. Cela indique à l'opération de tri si les éléments doivent être commutés ou non, permettant ainsi le tri.
— Fenton

il peut être possible de filtrer avec différentes propriétés
— Arvind

24

Excellente réponse Sohnee. Je voudrais ajouter que si vous avez un tableau d'objets et que vous souhaitez trier par clé, c'est presque la même chose, voici un exemple qui peut trier à la fois par date (numéro) ou par titre (chaîne):

    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;
    }

Pourrait également rendre les valeurs à l'intérieur comme des variables n1 [champ] vs n2 [champ] si c'est plus dynamique, gardez simplement la différence entre les chaînes et les nombres.


Les commentaires sur les réponses doivent être effectués à l'aide de la fonction de commentaires.
— Nicktar

6
@Nicktar C'est probablement publié comme une réponse pour la mise en forme. Mais ça ne fait pas de mal de toute façon
— 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);

Trier par un champ:

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 est négatif quand n1 <n2, positif quand n1> n2 et 0 quand n1 == n2
— Sébastien Stormacq

2
Merci! Je l'ai changé pour ceci: myArray.sort ((a, b): number => {return a.NumberProp - b.NumberProp;});
— Lrodriguez84

10

Trier les tableaux mixtes (alphabets et nombres)

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)


Merci beaucoup :)
— 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)


Bonjour, Bienvenue sur stackoverflow, stackoverflow.com/help/how-to-answer, veuillez lire cette documentation et fournir une description de ce qui doit être fait.
— Prateik Darji le

0

J'ai écrit celui-ci aujourd'hui en essayant de le recréer _.sortByen TypeScript, et j'ai pensé que je le laisserais à quiconque en aurait besoin.

// ** 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
    })
}

Usage:

Il attend un tableau de type générique T, d'où le cast pour <T extends {}>, ainsi que la saisie du paramètre et du type de retour de fonction avecT[]

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

** getByKeyfn trouvé ici

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.