Mam tablicę obiektów JavaScript:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
Jak mogę je posortować według wartości last_nom
w JavaScript?
Wiem o tym sort(a,b)
, ale wydaje się, że działa to tylko na ciągi i liczby. Czy muszę dodać toString()
metodę do moich obiektów?
javascript
arrays
sorting
Tyrone Slothrop
źródło
źródło
Odpowiedzi:
Łatwo jest napisać własną funkcję porównania:
Lub inline (bez Marco Demaio):
źródło
return a.last_nom.localeCompare(b.last_nom)
też będzie działać.return a.value - b.value;
(ASC)localeCompare
jest ważny, gdy używa się znaków akcentowanych w językach obcych, a także jest bardziej elegancki.Możesz także utworzyć funkcję dynamicznego sortowania, która sortuje obiekty według przekazywanej wartości:
Możesz mieć tablicę takich obiektów:
... i zadziała, gdy wykonasz:
Właściwie to już odpowiada na pytanie. Poniższa część została napisana, ponieważ wiele osób skontaktowało się ze mną, narzekając, że nie działa z wieloma parametrami .
Wiele parametrów
Poniższej funkcji można użyć do wygenerowania funkcji sortowania z wieloma parametrami sortowania.
Co pozwoli ci zrobić coś takiego:
Tablica podklas
Szczęście wśród nas, którzy mogą korzystać z ES6, który pozwala rozszerzać obiekty rodzime:
Umożliwiłoby to:
źródło
dynamicSort()
w powyższym przykładzie umieścisz wielkie litery przed małymi literami. Na przykład, jeśli mam wartościAPd
,Aklin
orazAbe
- wyników w ASC porządek powinien byćAbe
,Aklin
,APd
. Ale ze swoim przykładzie, wyniki sąAPd
,Abe
,Aklin
. W każdym razie, aby poprawić to zachowanie?var result = a[property].localeCompare(b[property]);
zamiastvar result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
.if( !isNaN(a[property]) ) a[property] = Number(a[property]); if( !isNaN(b[property]) ) b[property] = Number(b[property]);
W ES6 / ES2015 lub nowszym możesz to zrobić w następujący sposób:
Przed ES6 / ES2015
źródło
last_nom
stosowania tylko numer w tablicy:1
?objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom, undefined, {numberic: true}));
underscore.js
użyj podkreślenia, jego małego i niesamowitego ...
źródło
var sortedObjs = _.sortBy( objs, 'first_nom' );
.objs
będzie nie być sortowane się w wyniku tego. Funkcja zwróci posortowaną tablicę. To by było bardziej wyraźne.var reverseSortedObjs = _.sortBy( objs, 'first_nom' ).reverse();
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"> </script>
Lodash
dla tych, którzy wolą tenvar sortedObjs = _.sortBy( objs, 'first_nom' );
lub jeśli chcesz, aby było w innej kolejności:var sortedObjs = _.orderBy( objs, ['first_nom'],['dsc'] );
Nie rozumiem, dlaczego ludzie komplikują to:
W przypadku bardziej rygorystycznych silników:
Zamień operatora, aby sortować go w odwrotnej kolejności alfabetycznej.
źródło
if(a.count == b.count) return a.name > b.name; else return a.count > b.count;
Jeśli masz zduplikowane nazwiska, możesz je posortować według imion -
źródło
b
powinna ona nastąpić poa
tablicy. Jeśli zwracana jest liczba dodatnia, oznacza to, żea
powinna nastąpić późniejb
. Jeśli0
zostanie zwrócony, oznacza to, że są uważane za równe. Zawsze możesz przeczytać dokumentację: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…1, 0, -1
zanim o to poprosiłem. Po prostu nie znalazłem potrzebnych informacji.Proste i szybkie rozwiązanie tego problemu za pomocą dziedziczenia prototypów:
Przykład / użycie
Aktualizacja: Nie modyfikuje już oryginalnej tablicy.
źródło
Od 2018 r. Istnieje znacznie krótsze i eleganckie rozwiązanie. Po prostu użyj. Array.prototype.sort () .
Przykład:
źródło
a.value - b.value
Używane do porównywania atrybutów obiektu ( numery w tym przypadku) mogą być przyjęte dla różnych porach danych. Na przykład, wyrażenie regularne może być użyte do porównania każdej pary sąsiednich ciągów .Stara odpowiedź, która jest nieprawidłowa:
AKTUALIZACJA
Z komentarza Beauchamp:
Bardziej czytelny format:
Bez zagnieżdżonych trójskładników:
Objaśnienie:
Number()
będzie przesyłanytrue
do1
ifalse
do0
.źródło
arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))
Zamiast korzystać z niestandardowej funkcji porównania, możesz również utworzyć typ obiektu za pomocą niestandardowej
toString()
metody (która jest wywoływana przez domyślną funkcję porównania):źródło
Lodash.js ( nadzbiór Underscore.js )
Dobrze jest nie dodawać frameworka dla każdej prostej logiki, ale poleganie na dobrze przetestowanych frameworkach użytkowych może przyspieszyć rozwój i zmniejszyć liczbę błędów.
Lodash tworzy bardzo czysty kod i promuje bardziej funkcjonalny styl programowania . Na pierwszy rzut oka staje się jasne, jaki jest cel kodu.
Problem OP można po prostu rozwiązać jako:
Więcej informacji? Np. Mamy następujący zagnieżdżony obiekt:
Teraz możemy użyć skrótu _.property,
user.age
aby określić ścieżkę do właściwości, która powinna być dopasowana. Posortujemy obiekty użytkownika według zagnieżdżonej właściwości age. Tak, pozwala na dopasowanie zagnieżdżonych właściwości!Chcesz to odwrócić? Nie ma problemu. Użyj _.reverse .
Chcesz połączyć oba za pomocą łańcucha ?
Lub kiedy wolisz przepływ ponad łańcuchem
źródło
Możesz użyć
Najłatwiejszy sposób: Lodash
( https://lodash.com/docs/4.17.10#orderBy )
Ta metoda jest podobna do _.sortBy, z tą różnicą, że pozwala na określenie kolejności sortowania iteratów do sortowania według. Jeśli zamówienia nie są określone, wszystkie wartości są sortowane w porządku rosnącym. W przeciwnym razie podaj porządek „malejący” dla malejącego lub „rosnący” dla rosnącego sortowania odpowiednich wartości.
Argumenty
kolekcja (Array | Object): kolekcja do iteracji. [iteratees = [_. tożsamość]] (Array [] | Function [] | Object [] | string []): Ieruje sortowanie według. [zamówienia] (ciąg []): Porządki sortowania iteratów.
Zwroty
(Array): Zwraca nową posortowaną tablicę.
źródło
Istnieje wiele dobrych odpowiedzi, ale chciałbym zauważyć, że można je bardzo łatwo rozszerzyć, aby uzyskać znacznie bardziej złożone sortowanie. Jedyne, co musisz zrobić, to użyć operatora OR do połączenia funkcji porównania w następujący sposób:
gdzie
fn1
,fn2
... są zwracane funkcje sortowania [-1,0,1]. Powoduje to „sortowanie według fn1”, „sortowanie według fn2”, co jest prawie równe ORDER BY w SQL.To rozwiązanie opiera się na zachowaniu
||
operatora, który ocenia pierwsze ocenione wyrażenie, które można przekonwertować na true .Najprostsza forma ma tylko jedną wbudowaną funkcję:
Mając dwa kroki z
last_nom
,first_nom
porządek będzie wyglądać następująco:Ogólna funkcja porównania może wyglądać mniej więcej tak:
Funkcję tę można rozszerzyć o obsługę pól numerycznych, rozróżnianie wielkości liter, arbitralne typy danych itp.
Możesz ich użyć do łączenia ich według priorytetów sortowania:
Chodzi o to, że czysty JavaScript z funkcjonalnym podejściem może zabrać cię daleko bez zewnętrznych bibliotek lub złożonego kodu. Jest również bardzo skuteczny, ponieważ nie trzeba wykonywać analizy ciągów
źródło
Przykładowe użycie:
Scenariusz:
źródło
1, 0, -1
są używane do sortowania sortowania. Nawet z powyższym wyjaśnieniem, które wygląda bardzo dobrze - wciąż nie rozumiem tego. Zawsze myślę o tym,-1
jak przy użyciu właściwości długości tablicy, tzn .:arr.length = -1
oznacza, że element nie został znaleziony. Prawdopodobnie mieszam tutaj różne rzeczy, ale czy możesz mi pomóc zrozumieć, dlaczego cyfry1, 0, -1
są używane do określania kolejności? Dzięki.a
ib
, jeślia
jest większe niżb
dodaj 1 do indeksua
i umieść go z tyłub
, jeślia
jest mniejsze niżb
, odejmij 1a
i umieść przedb
. Jeślia
ib
są takie same, dodaj 0 doa
i pozostaw to miejsce.Nie widziałem tego szczególnego podejścia sugerowanego, więc oto sposób porównanie lakoniczny Lubię używać który pracuje dla obu
string
oraznumber
:Oto wyjaśnienie
sortBy()
:sortBy()
akceptuje wartość a,fn
która wybiera wartość z obiektu do użycia jako porównanie, i zwraca funkcję, do której można przekazać bezpośrednioArray.prototype.sort()
. W tym przykładzie używamyo.last_nom
jako wartości do porównania, więc za każdym razem, gdy otrzymujemy dwa obiekty,Array.prototype.sort()
takie jaki
Używamy
aby je porównać.
Pamiętając o tym
fn = o => o.last_nom
, możemy rozszerzyć funkcję porównania do odpowiednikaLogiczny
||
operator OR ma funkcję zwarcia, która jest bardzo przydatna w tym przypadku. Z powodu tego, jak to działa, oznacza to powyższą treśćJako dodatkowy bonus, oto ekwiwalent w ECMAScript 5 bez funkcji strzałek, co jest niestety bardziej szczegółowe:
źródło
Wiem, że to pytanie jest za stare, ale nie widziałem żadnej implementacji podobnej do mojej.
Ta wersja oparta jest na idiomie transformacji Schwartziana .
Oto przykład, jak go używać:
źródło
Sortowanie (więcej) Złożone tablice obiektów
Ponieważ prawdopodobnie napotykasz bardziej złożone struktury danych, takie jak ta tablica, rozwinąłbym to rozwiązanie.
TL; DR
Problem
Spotkałem poniżej i nie mogłem tego zmienić. Nie chciałem też tymczasowo spłaszczyć obiektu. Nie chciałem też używać podkreślenia / lodash, głównie ze względu na wydajność i zabawę, aby samodzielnie go wdrożyć.
Cel
Celem jest posortowanie go według
People.Name.name
a następnie wedługPeople.Name.surname
Przeszkody
Teraz w rozwiązaniu podstawowym używa notacji nawiasowej do obliczania właściwości do sortowania dynamicznego. Tutaj jednak musielibyśmy również dynamicznie konstruować notację nawiasową, ponieważ można by się spodziewać podobnych
People['Name.name']
będą działać - co nie działa.People['Name']['name']
Z drugiej strony samo robienie jest statyczne i pozwala tylko zejść n ty poziom.Rozwiązanie
Głównym dodatkiem tutaj będzie przejście po drzewie obiektów i określenie wartości ostatniego liścia, który musisz określić, a także dowolnego liścia pośredniego.
Przykład
Przykład roboczy na JSBin
źródło
Jeszcze jedna opcja:
domyślnie sortuje rosnąco.
źródło
Prosta funkcja sortująca tablicę obiektów według właściwości
Stosowanie:
źródło
Prosty sposób:
Zobacz, co
'.toLowerCase()'
jest konieczne, aby zapobiec błędom przy porównywaniu ciągów.źródło
objs.sort( (a,b) => b.last_nom.toLowerCase() < a.last_nom.toLowerCase() );
dodatkowe parametry opisowe dla kodu Ege Özcan
źródło
Łącząc dynamiczne rozwiązanie Ege z pomysłem Vinay, otrzymujesz ładne, solidne rozwiązanie:
Stosowanie:
źródło
Na przykład, musisz posortować według dwóch pól (nazwisko, imię), a nie jednego. Możesz użyć biblioteki Alasql, aby dokonać tego sortowania w jednym wierszu:
Spróbuj tego przykładu w jsFiddle .
źródło
źródło
Biorąc pod uwagę oryginalny przykład:
Sortuj według wielu pól:
Notatki
a.localeCompare(b)
jest powszechnie obsługiwana i wraca -1,0,1 jeślia<b
,a==b
,a>b
odpowiednio.||
w ostatnim wierszu dajelast_nom
pierwszeństwofirst_nom
.var age_order = left.age - right.age;
return -last_nom_order || -first_nom_order || -age_order;
źródło
Spróbuj tego,
źródło
Może być konieczne przekonwertowanie ich na małe litery, aby uniknąć pomyłek.
źródło
źródło
Korzystając z Ramda,
npm install ramda
źródło
To prosty problem, nie wiem, dlaczego ludzie mają tak złożone rozwiązanie.
Prosta funkcja sortowania (oparta na algorytmie szybkiego sortowania ):
Użyj przykładu:
źródło