Próbuję posortować tablicę z obiektami na podstawie wielu atrybutów. To znaczy, jeśli pierwszy atrybut jest taki sam między dwoma obiektami, do porównania tych dwóch obiektów należy użyć drugiego atrybutu. Na przykład rozważmy następującą tablicę:
var patients = [
[{name: 'John', roomNumber: 1, bedNumber: 1}],
[{name: 'Lisa', roomNumber: 1, bedNumber: 2}],
[{name: 'Chris', roomNumber: 2, bedNumber: 1}],
[{name: 'Omar', roomNumber: 3, bedNumber: 1}]
];
Sortując je według roomNumber
atrybutu, użyłbym następującego kodu:
var sortedArray = _.sortBy(patients, function(patient) {
return patient[0].roomNumber;
});
Działa to dobrze, ale jak mam postępować, aby „John” i „Lisa” zostały odpowiednio posortowane?
źródło
[0]
Podziałowy jest wymagane, ponieważ w przykładzie początkowym,patients
jest tablicą tablic. Dlatego też „prostsze rozwiązanie” w poście na blogu, o którym mowa w innym komentarzu, nie będzie tutaj działać.Oto hacky trik, którego czasami używam w takich przypadkach: połącz właściwości w taki sposób, aby wynik był możliwy do sortowania:
Jednak, jak powiedziałem, jest to dość hakerskie. Aby zrobić to poprawnie, prawdopodobnie chciałbyś faktycznie użyć podstawowej
sort
metody JavaScript :Oczywiście, to będzie uporządkować swoją tablicę w miejscu. Jeśli chcesz posortowaną kopię (tak jak
_.sortBy
by ci to dało), najpierw sklonuj tablicę:Z nudów właśnie napisałem ogólne rozwiązanie (aby posortować według dowolnej liczby kluczy) również na to: spójrz .
źródło
return [patient[0].roomNumber, patient[0].name];
wystarczy bezjoin
?compare
wartości uchwytów, które nie są prymitywne - wartościundefined
,null
lub zwykły obiekty?Wiem, że spóźniłem się na imprezę, ale chciałem to dodać dla tych, którzy potrzebują czystszego i szybszego rozwiązania, które już sugerowali. Wywołania sortBy można łączyć w kolejności od najmniej ważnej właściwości do najważniejszej właściwości. W poniższym kodzie tworzę nową tablicę pacjentów posortowaną według nazwy w RoomNumber z oryginalnej tablicy o nazwie pacjenci .
źródło
przy okazji twój inicjator dla pacjentów jest trochę dziwny, prawda? dlaczego nie zainicjujesz tej zmiennej jako - jako prawdziwej tablicy obiektów - możesz to zrobić za pomocą _.flatten (), a nie jako tablicę tablic pojedynczego obiektu, może to błąd literówki):
Posortowałem listę inaczej i dodałem Kiko do łóżka Lisy; tylko dla zabawy i zobacz, jakie zmiany zostaną wprowadzone ...
sprawdź posortowane, a zobaczysz to
więc moja odpowiedź brzmi: użyj tablicy w swojej funkcji zwrotnej jest to dość podobne do odpowiedzi Dana Tao , po prostu zapomniałem o złączeniu (może dlatego, że usunąłem tablicę tablic unikalnych pozycji :))
Używając struktury danych, to byłoby :
a ładowanie testowe byłoby interesujące ...
źródło
Żadna z tych odpowiedzi nie jest idealna jako metoda ogólnego przeznaczenia do korzystania z wielu pól w sortowaniu. Wszystkie powyższe podejścia są nieefektywne, ponieważ wymagają wielokrotnego sortowania tablicy (co na wystarczająco dużej liście może spowolnić działanie) lub generują ogromne ilości śmieci, które maszyna wirtualna będzie musiała wyczyścić (i ostatecznie spowolnić program wyłączony).
Oto rozwiązanie, które jest szybkie, wydajne, łatwo umożliwia odwrotne sortowanie i może być używane z
underscore
lublodash
lub bezpośrednio zArray.sort
Najważniejszą częścią jest
compositeComparator
metoda, która przyjmuje tablicę funkcji komparatora i zwraca nową funkcję komparatora złożonego.Będziesz także potrzebować funkcji komparatora do porównywania pól, według których chcesz sortować.
naturalSort
Funkcja stworzy komparator podana konkretna dziedzina. Napisanie komparatora do sortowania wstecznego jest również trywialne.(Cały dotychczasowy kod jest wielokrotnego użytku i może być przechowywany na przykład w module narzędziowym)
Następnie musisz utworzyć komparator złożony. W naszym przykładzie wyglądałoby to tak:
Spowoduje to posortowanie według numeru pokoju, po którym następuje nazwa. Dodanie dodatkowych kryteriów sortowania jest trywialne i nie wpływa na wydajność sortowania.
Zwraca następujące dane
Powodem, dla którego wolę tę metodę jest to, że pozwala ona na szybkie sortowanie na dowolnej liczbie pól, nie generuje dużo śmieci ani nie wykonuje konkatenacji ciągów wewnątrz sortowania i może być łatwo używana, aby niektóre kolumny były sortowane odwrotnie, podczas gdy kolumny kolejności używają naturalnych sortować.
źródło
Prosty przykład z http://janetriley.net/2014/12/sort-on-multiple-keys-with-underscores-sortby.html (dzięki uprzejmości @MikeDevenney)
Kod
Twoje dane
źródło
Być może underscore.js lub po prostu silniki Javascript są teraz inne niż wtedy, gdy pisano te odpowiedzi, ale udało mi się to rozwiązać, zwracając po prostu tablicę kluczy sortowania.
W akcji zobacz to skrzypce: https://jsfiddle.net/mikeular/xenu3u91/
źródło
Po prostu zwróć tablicę właściwości, według których chcesz posortować:
Składnia ES6
Składnia ES5
Nie ma to żadnych skutków ubocznych konwersji liczby na ciąg.
źródło
Możesz połączyć właściwości, według których chcesz sortować w iteratorze:
lub coś równoważnego.
UWAGA: Ponieważ konwertujesz atrybut numeryczny roomNumber na łańcuch, musiałbyś coś zrobić, gdybyś miał numery pokoi> 10. W przeciwnym razie 11 wystąpi przed 2. Aby rozwiązać problem, możesz wypełnić zera wiodące, np. 01 zamiast 1.
źródło
Myślę, że lepiej użyj
_.orderBy
zamiastsortBy
:źródło
_.orderBy
działa, ale jest to metoda biblioteki lodash, a nie podkreślenia: lodash.com/docs/4.17.4#order Przez lodash jest głównie zastępczym zamiennikiem podkreślenia, więc może być odpowiedni dla OP.Jeśli używasz Angulara, możesz użyć jego filtra liczbowego w pliku html zamiast dodawać jakiekolwiek moduły obsługi JS lub CSS. Na przykład:
W tym przykładzie, jeśli val = 1234567, zostanie wyświetlony jako
Przykład i dalsze wskazówki na: https://docs.angularjs.org/api/ng/filter/number
źródło