TypeScript sortuje tablicę


154

Próbowałem wymyślić bardzo dziwny problem, na który natknąłem się z maszynopisem. To było traktowanie wbudowanego wyrażenia boolowskiego jako dowolnego typu pierwszej wartości zamiast pełnego wyrażenia.

Więc jeśli spróbujesz czegoś prostego, takiego jak poniższe:

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

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

Spróbuj

W metodzie sortowania pojawi się błąd informujący, że parametry nie pasują do żadnej sygnatury celu wywołania, ponieważ wynik jest liczbowy, a nie logiczny. Chyba czegoś mi brakuje, bo jestem prawie pewien, że n1> n2 to wyrażenie logiczne.

Odpowiedzi:


180

Błąd jest całkowicie poprawny.

Jak próbuje ci powiedzieć, .sort()przyjmuje funkcję, która zwraca liczbę, a nie wartość logiczną.

Musisz zwrócić wartość ujemną, jeśli pierwsza pozycja jest mniejsza; dodatnia, jeśli jest większa, lub zero, jeśli są równe.


56
Dlatego używamy TypeScript! :-)
Stephen Chung

226

Liczby

Podczas sortowania liczb możesz skorzystać z kompaktowego porównania:

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

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

tj. -zamiast <.

Inne rodzaje

Jeśli porównujesz cokolwiek innego, musisz przekonwertować porównanie na liczbę.

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

Obiekty

W przypadku obiektów możesz sortować według właściwości, pamiętaj o powyższych informacjach dotyczących możliwości skracania typów numerów. Poniższy przykład działa niezależnie od typu.

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

Czy ktoś mógłby wyjaśnić, dlaczego w przypadku testu less-than „Roy@my.net” zwraca wartość true dla mniej niż „bob@my.net”? np .: let myTest = ('Roy@my.net' <'bob@my.net'); // zwraca prawdę dla mnie ... :(
Wallace Howery

1
w drugim przypadku możesz użyć localeCompare () do porównania ciągów znaków w bieżącym locale, co zwraca liczbę
neural5torm

Proszę wyjaśnij mi, jak (n1,n2)=>n1-n2będzie wykonywana lub działa ekspresja .. ??
Rahul Chaudhari

1
@RahulChaudhari w przykładzie liczbowym, jest to funkcja, która pobiera liczby n1i n2, w ramach funkcji n1-n2, którą zwraca , będzie to liczba dodatnia, zero lub liczba ujemna. Informuje to operację sortowania, czy elementy muszą zostać przełączone, czy nie, umożliwiając w ten sposób sortowanie.
Fenton

możliwe jest filtrowanie z innymi właściwościami
Arvind

24

Świetna odpowiedź Sohnee. Chciałbym dodać, że jeśli masz tablicę obiektów i chcesz sortować według klucza, to jest prawie taki sam, oto przykład takiego, który może sortować zarówno według daty (liczby), jak i tytułu (ciągu):

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

Może również sprawić, że wartości wewnątrz będą zmiennymi n1 [pole] vs n2 [pole], jeśli jest bardziej dynamiczne, po prostu zachowaj różnicę między łańcuchami a liczbami.


Komentowanie odpowiedzi powinno odbywać się za pomocą funkcji komentarzy.
Nicktar,

6
@Nicktar Prawdopodobnie została opublikowana jako odpowiedź na formatowanie. Ale i tak nie szkodzi
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);

Sortuj według jakiegoś pola:

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 jest ujemne, gdy n1 <n2, dodatnie, gdy n1> n2 i 0, gdy n1 == n2
Sébastien Stormacq

2
Dzięki! Zmieniłem to w tym celu: myArray.sort ((a, b): number => {return a.NumberProp - b.NumberProp;});
Lrodriguez84

10

Sortuj mieszane tablice (alfabety i cyfry)

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)


Dziękuję bardzo :)
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)


Witaj, Witamy w stackoverflow, stackoverflow.com/help/how-to-answer, przeczytaj tę dokumentację i opisz, co należy zrobić.
Prateik Darji

0

Napisałem to dzisiaj, próbując odtworzyć _.sortByw TypeScript i pomyślałem, że zostawię to każdemu w potrzebie.

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

Stosowanie:

Oczekuje tablicy typu ogólnego T, stąd rzutowanie dla <T extends {}>, a także wpisanie parametru i zwracanego typu funkcji zT[]

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

** getByKeyfn znaleziony tutaj

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.