Sortuj tablicę według imienia (alfabetycznie) w JavaScript

644

Mam tablicę (patrz poniżej jeden obiekt w tablicy), którą muszę posortować według imienia za pomocą JavaScript. Jak mogę to zrobić?

var user = {
   bio: null,
   email:  "[email protected]",
   firstname: "Anna",
   id: 318,
   lastAvatar: null,
   lastMessage: null,
   lastname: "Nickson",
   nickname: "anny"
};
Jonathan Clark
źródło
możliwy duplikat tablicy Sortuj obiektów JavaScript
Felix Kling

Odpowiedzi:

1065

Załóżmy, że masz tablicę users. Możesz użyćusers.sort i przekazać funkcję, która pobiera dwa argumenty i porównać je (komparator)

Powinien powrócić

  • coś negatywnego, jeśli pierwszy argument jest mniejszy niż drugi (powinien zostać umieszczony przed drugim w wynikowej tablicy)
  • coś pozytywnego, jeśli pierwszy argument jest większy (powinien zostać umieszczony po drugim)
  • 0, jeśli te dwa elementy są równe.

W naszym przypadku, jeśli dwa elementy są ai bchcemy porównać a.firstnameib.firstname

Przykład:

users.sort(function(a, b){
    if(a.firstname < b.firstname) { return -1; }
    if(a.firstname > b.firstname) { return 1; }
    return 0;
})

Ten kod będzie działał z dowolnym typem.

Zauważ, że w „prawdziwym życiu” ™ często chcesz ignorować wielkość liter, poprawnie sortować znaki diakrytyczne, dziwne symbole, takie jak ß itp. Podczas porównywania ciągów, więc możesz chcieć użyć localeCompare. Zobacz inne odpowiedzi dla jasności.

RiaD
źródło
5
Friggin super ... Sortuję listę węzłów według id ... działa jak urok. Dzięki za tonę!
Cody,
74
Dla tych, którzy przyjdą później, odpowiedź Mrchiefa jest lepsza, ponieważ nie uwzględnia wielkości liter.
mlienau
25
@mlienau, nie nazwałbym tego lepszym ani gorszym. To po prostu kolejny
RiaD
19
@RiaD wystarczy. Po prostu nie mogę pomyśleć o wielu przypadkach sortowania przedmiotów alfabetycznie, w tym pancerza, w których „Zebra” pojawia się na liście przed „jabłkiem”, byłoby bardzo przydatne.
mlienau
15
Ten kod działa tylko w krajach anglojęzycznych. W innych krajach powinieneś używać odpowiedzi ovunccetin zlocaleCompare .
Spoike
541

Najkrótszy możliwy kod z ES6!

users.sort((a, b) => a.firstname.localeCompare(b.firstname))

Podstawowa obsługa String.prototype.localeCompare () jest uniwersalna!

Nachiketha
źródło
27
Zdecydowanie najlepsza odpowiedź, jeśli mieszkasz w 2017 roku
nathanbirrell,
52
Najlepsza odpowiedź również, jeśli mieszkasz w 2018 roku;)
Simone
49
Prawdopodobnie będzie najlepszą odpowiedzią na 2019 rok.
Ahmad Maleki
23
Może 2020? czy naaa?
kspearrin
14
Ach, człowieku, w 2030 roku ziemia zalewa i to działa tylko w górach.
Starfs
343

Coś takiego:

array.sort(function(a, b){
 var nameA=a.name.toLowerCase(), nameB=b.name.toLowerCase();
 if (nameA < nameB) //sort string ascending
  return -1;
 if (nameA > nameB)
  return 1;
 return 0; //default return value (no sorting)
});
Mrchief
źródło
43
Podczas sortowania ciągów znaków „toLowerCase ()” jest bardzo ważne - duże litery mogą wpływać na sortowanie.
MarzSocks,
3
W przypadku, gdy ktoś zastanawia się, na co wpływa toLowerCase, nie jest to wiele:'a'>'A' //true 'z'>'a' //true 'A'>'z' //false
SimplGy
14
@SimplGy Twierdzę, że jego wpływ jest nieco większy, niż można to przypisać. Na przykład, jak stwierdzono w komentarzach do zaakceptowanej odpowiedzi, ważne jest, aby wiedzieć, czy funkcja sortowania posortuje łańcuch 'Zebra'wyżej niż łańcuch 'apple', co zrobi, jeśli go nie użyjesz .toLowerCase().
PrinceTyke
1
@PrinceTyke tak, to dobry człowiek. 'Z' < 'a' // trueoraz'z' < 'a' // false
SimplGy,
2
Wszystkie ważne punkty i powiedziałbym, że sortowanie jest zawsze „zależne”. Jeśli sortujesz według nazw, rozróżnianie wielkości liter może nie mieć znaczenia. W innych przypadkach może. Niezależnie od tego uważam, że przystosowanie się do konkretnej sytuacji nie jest trudne, gdy tylko dostaniesz podstawowy pomysł.
Mrchief
336

W porównaniu struny zawierać znaki Unicode można użyć localeComparefunkcji z Stringklasy tak:

users.sort(function(a,b){
    return a.firstname.localeCompare(b.firstname);
})
ovunccetin
źródło
3
String.localeCompare nie obsługuje Safari i IE <11 :)
CORSAIR
13
@CORSAIR jest obsługiwany, to tylko drugi i trzeci parametr, który nie jest obsługiwany.
Codler,
6
@CORSAIR użycie w tym przykładzie jest obsługiwane we wszystkich głównych przeglądarkach IE: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . LocaleCompare bierze również pod uwagę wielkie litery, więc myślę, że tę implementację należy uznać za najlepszą praktykę.
Matt Jensen,
9
users.sort ((a, b) => a. pierwsza nazwa.localeCompare (b. pierwsza nazwa)) // Krótka i słodka wersja ES6!
Nachiketha,
4
czołgi bracie. w użyciu ES6users.sort((a, b) => a.name.localeCompare(b.name))
Mohmmad Ebrahimi Aval
32

Miły mały jeden wkładka ES6:

users.sort((a, b) => a.firstname !== b.firstname ? a.firstname < b.firstname ? -1 : 1 : 0);
Sam Logan
źródło
2
Ten jest niekompletny, ponieważ nie obsługuje poprawnie równych wartości.
Karl-Johan Sjögren
1
Oczywiście, dziękuję za wykrycie tego, dodałem kontrolę dopasowania wartości
Sam Logan
nie złe Myślę, że jeśli naprawdę chcesz to wszystko w jednej linii, zagnieżdżone ternaries się mylące dla czytelności choć
russter
24

Możemy użyć localeCompare, ale musimy również sprawdzić klucze pod kątem wartości falsey

Poniższy kod nie będzie działał, jeśli brakuje jednej nazwy lname.

obj.sort((a, b) => a.lname.localeCompare(b.lname))

Musimy więc sprawdzić wartość falsey jak poniżej

let obj=[
{name:'john',lname:'doe',address:'Alaska'},
{name:'tom',lname:'hopes',address:'California'},
{name:'harry',address:'Texas'}
]
let field='lname';
console.log(obj.sort((a, b) => (a[field] || "").toString().localeCompare((b[field] || "").toString())));

LUB

możemy użyć lodash, to bardzo proste. Wykryje zwrócone wartości, tj. Liczbę lub ciąg znaków, i odpowiednio posortuje.

import sortBy from 'lodash/sortBy';
sortBy(obj,'name')

https://lodash.com/docs/4.17.5#sortBy

sumit
źródło
2
Lodash jest całkiem fajny! Nie słyszałem o tym wcześniej. Działa świetnie!
Derk Jan Speelman
15

underscorejs oferuje bardzo przyjemną funkcję _.sortBy:

_.sortBy([{a:1},{a:3},{a:2}], "a")

lub możesz użyć niestandardowej funkcji sortowania:

_.sortBy([{a:"b"},{a:"c"},{a:"a"}], function(i) {return i.a.toLowerCase()})
Peter T.
źródło
2
drugi przykład dotyczy zwracania ciągów. Czy sortBywykryte zwracane wartości są łańcuchami, a zatem dokonuje sortowania alfabetycznego? Dzięki
superjos
12

W przypadku, gdy mamy do sortowania nazw lub coś ze znaków specjalnych, takich jak ń lub aeiou (świetlicy w języku hiszpańskim) możemy wykorzystać params lokalizacje ( es dla hiszpańskiego w tym przypadku) i opcje jak poniżej:

let user = [{'firstname': 'Az'},{'firstname': 'Áb'},{'firstname':'ay'},{'firstname': 'Ña'},{'firstname': 'Nz'},{'firstname': 'ny'}];


user.sort((a, b) => a.firstname.localeCompare(b.firstname, 'es', {sensitivity: 'base'}))


console.log(user)

Oficjalne opcje ustawień regionalnych można znaleźć tutaj w iana , es (hiszpański), de (niemiecki), fr (francuski). O podstawie wrażliwości oznacza:

Tylko ciągi, które różnią się literami podstawowymi, są porównywane jako nierówne. Przykłady: a ≠ b, a = á, a = A.

Eeeus
źródło
8

Zasadniczo możesz sortować tablice za pomocą metody sortowania, ale jeśli chcesz sortować obiekty, musisz przekazać funkcję, aby posortować metodę tablicy, więc dam ci przykład za pomocą tablicy

user = [{
bio: "<null>",
email: "[email protected]",
firstname: 'Anna',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
},
{
bio: "<null>",
email: "[email protected]",
firstname: 'Senad',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
},
{
bio: "<null>",
email: "[email protected]",
firstname: 'Muhamed',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
}];

var ar = user.sort(function(a, b)
{
  var nA = a.firstname.toLowerCase();
  var nB = b.firstname.toLowerCase();

  if(nA < nB)
    return -1;
  else if(nA > nB)
    return 1;
 return 0;
});
Senad Meškin
źródło
po co zwracać 0 na końcu?
Nobita
=, gdy łańcuchy są takie same
Senad Meškin
ale w takim przypadku nie należy tego elseusuwać? W przeciwnym razie return 0nigdy nie zostanie to odczytane
Nobita,
2
to nie jest „else”, to „else if”
Senad Meškin
8

Zainspirowany odpowiedzią

users.sort((a,b) => (a.firstname  - b.firstname));
Isuru Siriwardana
źródło
8

Bardziej zwarta notacja:

user.sort(function(a, b){
    return a.firstname === b.firstname ? 0 : a.firstname < b.firstname ? -1 : 1;
})
James Andrews
źródło
jest bardziej zwarty, ale narusza jego umowę: sign(f(a, b)) =-sign(f(b, a))(dla a = b)
RiaD
3
powrót a.firstname == b.firstnamenależy użyć ===do kompletności
puiu
6

także dla sortowania asec i desc, możesz użyć tego: załóżmy, że mamy zmienną SortType, która określa sortowanie rosnące lub malejące, jakie chcesz:

 users.sort(function(a,b){
            return   sortType==="asc"? a.firstName.localeCompare( b.firstName): -( a.firstName.localeCompare(  b.firstName));
        })
Ghazaleh javaheri
źródło
5

Uogólnioną funkcję można zapisać jak poniżej

    function getSortedData(data, prop, isAsc) {
        return data.sort((a, b) => (a[prop] < b[prop] ? -1 : 1) * (isAsc ? 1 : -1));
   }

możesz przekazać poniższe parametry

  1. Dane, które chcesz posortować
  2. Właściwość w danych według niej powinna zostać posortowana
  3. Ostatni parametr jest typu logicznego. Sprawdza, czy chcesz sortować rosnąco lub malejąco
Santosh
źródło
4

próbować

users.sort((a,b)=> (a.firstname>b.firstname)*2-1)

Kamil Kiełczewski
źródło
2
funkcja sortowania powinna zwrócić -1,0,1. ten zwraca tylko -1,1.
Radu Luncasu
@RaduLuncasu - czy możesz podać dane testowe (tablica użytkowników), które pokazują, że powyższe rozwiązanie daje zły wynik? (o ile wiem, brak zer nie stanowi problemu)
Kamil Kiełczewski
Jeśli funkcja porównawcza (a, b) zwraca 0, pozostaw aib niezmienione względem siebie, ale posortowane względem wszystkich różnych elementów.
Radu Luncasu
@RaduLuncasu ok, ale te informacje nie oznaczają, że zero jest obowiązkowe. Najlepszym sposobem, aby to pokazać, jest przygotowanie danych, które nie działają - ale o ile wiem, jest to niemożliwe - np.[9,8,7,6,5,1,2,3].sort((a,b) => a<b ? -1 : 1)
Kamil Kiełczewski
3

Możesz użyć tego do obiektów

transform(array: any[], field: string): any[] {
return array.sort((a, b) => a[field].toLowerCase() !== b[field].toLowerCase() ? a[field].toLowerCase() < b[field].toLowerCase() ? -1 : 1 : 0);}
Andre Coetzee
źródło
2

jednym słowem możesz użyć tej metody

users.sort(function(a,b){return a.firstname < b.firstname ? -1 : 1});
FarukT
źródło
1

Możesz użyć wbudowanej metody tablicowej sort. Ta metoda przyjmuje parametr zwrotny jako parametr



    // custom sort function to be passed as param/callback to the Array's sort method
    function myCustomSort(a, b) {
        return (a.toLowerCase() > b.toLowerCase()) ? 1 : -1;
    }

    // Actual method to be called by entity that needs sorting feature
    function sortStrings() {
        var op = Array.prototype.sort.call(arguments, myCustomSort);
    }

    // Testing the implementation
    var sortedArray = sortStrings("Burger", "Mayo1", "Pizza", "boxes", "Apples", "Mayo");
    console.log(sortedArray); //["Apples", "boxes", "Burger", "Mayo", "Mayo1", "Pizza"]


Kluczowe punkty, na które należy zwrócić uwagę, aby zrozumieć ten kod.

  1. W tym przypadku metoda niestandardowa myCustomSortpowinna zwracać +1 lub -1 dla każdej pary elementów (z tablicy wejściowej).
  2. Użyj toLowerCase()/ toUpperCase()w niestandardowej metodzie zwrotnej sortowania, aby różnica wielkości liter nie wpływała na poprawność procesu sortowania.

Mam nadzieję, że to dość jasne wytłumaczenie. Jeśli uważasz, że możesz dodać komentarz, potrzebujesz więcej informacji.

Twoje zdrowie!

shanky
źródło
Niewłaściwa odpowiedź, ponieważ wykonuje ona tylko mniej niż i więcej niż kontrole, a nie równą kontrolę.
Steel Brain
nie wprowadza także nowych elementów do tabeli, w porównaniu z żadnymi odpowiedziami, które pojawiały się tam od ~ 2011 roku.
amenthes
1

Wrzuciłem najlepsze odpowiedzi do prototypu, aby posortować według klucza.

Array.prototype.alphaSortByKey= function (key) {
    this.sort(function (a, b) {
        if (a[key] < b[key])
            return -1;
        if (a[key] > b[key])
            return 1;
        return 0;
    });
    return this;
};
msponagle
źródło
0

Możesz użyć czegoś podobnego, aby pozbyć się rozróżniania wielkości liter

users.sort(function(a, b){

  //compare two values
  if(a.firstname.toLowerCase() < b.firstname.toLowerCase()) return -1;
  if(a.firstname.toLowerCase() > b.firstname.toLowerCase()) return 1;
  return 0;

})
SAN_WEB
źródło
7
Taka sama odpowiedź jak Mrchief. Kolejną wadą jest to, że toLowerCase jest wykonywany cztery razy w porównaniu, a nie dwa razy.
amenthes
0

Moja implementacja działa świetnie w starszych wersjach ES:

sortObject = function(data) {
    var keys = Object.keys(data);
    var result = {};

    keys.sort();

    for(var i = 0; i < keys.length; i++) {
        var key = keys[i];

        result[key] = data[key];
    }

    return result;
};
skrajny
źródło
0

Dla przypomnienia, jeśli chcesz mieć nazwaną funkcję sortowania, składnia jest następująca:

let sortFunction = (a, b) => {
 if(a.firstname < b.firstname) { return -1; }
 if(a.firstname > b.firstname) { return 1; }
 return 0;
})
users.sort(sortFunction)

Pamiętaj, że następujące NIE działa:

users.sort(sortFunction(a,b))
Katinka Hesselink
źródło