Urutkan array berdasarkan nama depan (berdasarkan abjad) dalam Javascript

647

Saya mendapat sebuah array (lihat di bawah untuk satu objek dalam array) yang perlu saya urutkan berdasarkan nama depan menggunakan JavaScript. Bagaimana saya bisa melakukannya?

var user = {
   bio: null,
   email:  "[email protected]",
   firstname: "Anna",
   id: 318,
   lastAvatar: null,
   lastMessage: null,
   lastname: "Nickson",
   nickname: "anny"
};
Jonathan Clark
sumber
kemungkinan duplikat susunan Sortir JavaScript Objek
Felix Kling

Jawaban:

1068

Misalkan Anda memiliki array users. Anda dapat menggunakan users.sortdan meneruskan fungsi yang membutuhkan dua argumen dan membandingkannya (pembanding)

Itu harus kembali

  • sesuatu yang negatif jika argumen pertama kurang dari detik (harus ditempatkan sebelum argumen kedua dalam array yang dihasilkan)
  • sesuatu yang positif jika argumen pertama lebih besar (harus ditempatkan setelah argumen kedua)
  • 0 jika kedua elemen tersebut sama.

Dalam kasus kami jika dua elemen adalah adan bkami ingin membandingkan a.firstnamedanb.firstname

Contoh:

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

Kode ini akan bekerja dengan tipe apa pun.

Perhatikan bahwa dalam "kehidupan nyata" ™ Anda sering ingin mengabaikan huruf besar-kecil, urutkan dengan benar diakritik, simbol aneh seperti ß, dll saat Anda membandingkan string, jadi Anda mungkin ingin menggunakannya localeCompare. Lihat jawaban lain untuk kejelasan.

RiaD
sumber
5
Friggin luar biasa ... Saya sedang mengurutkan nodelist oleh id ... bekerja seperti pesona. Terima kasih!
Cody
74
Bagi mereka yang datang di kemudian hari, jawaban Mrchief lebih baik karena tidak sensitif huruf.
mlienau
25
@ Mlienau, saya tidak akan menyebutnya lebih baik atau lebih buruk. Ini hanya lain
RiaD
19
@RiaD cukup adil. Hanya tidak bisa memikirkan banyak kasus menyortir item secara alfabet termasuk casing, di mana 'Zebra' muncul dalam daftar sebelum 'apel', akan sangat berguna.
mlienau
15
Kode ini hanya akan berfungsi di negara-negara berbahasa Inggris. Di negara lain Anda harus menggunakan jawaban ovunccetin denganlocaleCompare .
Spoike
546

Kode terpendek dengan ES6!

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

String.prototype.localeCompare () dukungan dasar bersifat universal!

Nachiketha
sumber
27
Sejauh ini jawaban terbaik jika Anda tinggal di 2017
nathanbirrell
52
Jawaban terbaik juga jika Anda hidup pada tahun 2018;)
Simone
49
Mungkin akan menjadi jawaban terbaik untuk 2019 juga.
Ahmad Maleki
23
2020 mungkin? atau naaa?
kspearrin
15
ah manusia, pada 2030 bumi banjir dan ini hanya berfungsi di pegunungan.
Starfs
343

Sesuatu seperti ini:

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)
});
Tuan
sumber
43
Saat menyortir string 'toLowerCase ()' sangat penting - huruf kapital dapat memengaruhi sortir Anda.
MarzSocks
3
Jika ada orang lain yang bertanya-tanya apa dampak toLowerCase, itu tidak banyak:'a'>'A' //true 'z'>'a' //true 'A'>'z' //false
SimplGy
14
@SimplGy Saya berpendapat bahwa dampaknya sedikit lebih dari yang Anda berikan kredit untuk itu. Misalnya, seperti yang dinyatakan dalam komentar pada jawaban yang diterima, penting untuk mengetahui apakah fungsi sortir Anda akan mengurutkan string 'Zebra'lebih tinggi daripada string 'apple', yang akan dilakukan jika Anda tidak menggunakan .toLowerCase().
PrinceTyke
1
@PrinceTyke ya itu pria kasus yang baik. 'Z' < 'a' // truedan'z' < 'a' // false
SimplGy
2
Semua poin yang valid dan saya katakan penyortiran selalu merupakan hal yang "tergantung". Jika Anda mengurutkan berdasarkan nama, sensitivitas huruf mungkin tidak masalah. Dalam kasus lain mungkin. Bagaimanapun, saya pikir mengadopsi ke situasi spesifik seseorang tidak sulit setelah Anda mendapatkan ide inti.
Mrchief
336

Jika string dibandingkan berisi karakter unicode Anda dapat menggunakan localeComparefungsi dari Stringkelas seperti berikut ini:

users.sort(function(a,b){
    return a.firstname.localeCompare(b.firstname);
})
ovunccetin
sumber
3
String.localeCompare tidak mendukung Safari dan IE <11 :)
CORSAIR
13
@CORSAIR didukung, hanya parameter kedua dan ketiga yang tidak didukung.
Codler
6
@CORSAIR penggunaan dalam contoh ini didukung di semua browser IE utama: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . LocaleCompare juga memperhitungkan kapitalisasi akun, jadi saya pikir implementasi ini harus dianggap sebagai praktik terbaik.
Matt Jensen
9
users.sort ((a, b) => a.firstname.localeCompare (b.firstname)) // Pendek dan manis versi ES6!
Nachiketha
4
tank saudara. dalam penggunaan ES6users.sort((a, b) => a.name.localeCompare(b.name))
Mohmmad Ebrahimi Aval
32

ES6 satu liner kecil yang bagus:

users.sort((a, b) => a.firstname !== b.firstname ? a.firstname < b.firstname ? -1 : 1 : 0);
Sam Logan
sumber
2
Yang ini tidak lengkap karena tidak menangani nilai yang sama dengan benar.
Karl-Johan Sjögren
1
Tentu saja, terima kasih telah melihatnya, saya telah menambahkan cek untuk nilai yang cocok
Sam Logan
tidak buruk saya kira jika Anda benar-benar ingin semuanya dalam satu baris, terner yang bersarang menjadi membingungkan untuk dibaca
russter
24

Kita dapat menggunakan localeCompare tetapi perlu memeriksa kunci juga untuk nilai falsey

Kode di bawah ini tidak akan berfungsi jika satu entri memiliki nama yang hilang.

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

Jadi kita perlu memeriksa nilai falsey seperti di bawah ini

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

ATAU

kita bisa menggunakan lodash, ini sangat sederhana. Ini akan mendeteksi nilai-nilai yang dikembalikan yaitu apakah angka atau string dan melakukan pengurutan yang sesuai.

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

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

sumit
sumber
2
Lodash cukup rapi! Belum pernah mendengarnya sebelumnya. Bagus sekali!
Derk Jan Speelman
15

underscorejs menawarkan fungsi _.sortBy yang sangat bagus:

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

atau Anda dapat menggunakan fungsi pengurutan khusus:

_.sortBy([{a:"b"},{a:"c"},{a:"a"}], function(i) {return i.a.toLowerCase()})
Peter T.
sumber
2
contoh kedua melibatkan string yang dikembalikan. Apakah sortBymendeteksi nilai yang dikembalikan adalah string dan dengan demikian melakukan pengurutan alfabet? Terima kasih
superjos
12

Jika kita menyortir nama atau sesuatu dengan karakter khusus, seperti ñ atau áéíóú (commons dalam bahasa Spanyol) kita dapat menggunakan params locales ( es untuk bahasa Spanyol dalam kasus ini) dan opsi seperti ini:

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)

Pilihan lokasi resmi dapat ditemukan di sini di iana , es (spanyol), de (Jerman), fr (Prancis). Tentang basis sensitivitas berarti:

Hanya string yang berbeda dalam huruf dasar yang dibandingkan sebagai tidak sama. Contoh: a ≠ b, a = á, a = A.

Emeeus
sumber
8

Pada dasarnya Anda dapat mengurutkan array dengan metode sortir, tetapi jika Anda ingin mengurutkan objek maka Anda harus melewati fungsi untuk mengurutkan metode array, jadi saya akan memberi Anda contoh menggunakan array Anda

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
sumber
mengapa mengembalikan 0 di akhir?
Nobita
=, ketika string sama
Senad Meškin
tetapi dalam kasus itu tidakkah elseharus dihapus? Kalau tidak, itu return 0tidak akan pernah dibaca
Nobita
2
itu bukan "lain", itu "lain kalau"
Senad Meškin
8

Terinspirasi dari jawaban ini ,

users.sort((a,b) => (a.firstname  - b.firstname));
Isuru Siriwardana
sumber
8

Notasi yang lebih ringkas:

user.sort(function(a, b){
    return a.firstname === b.firstname ? 0 : a.firstname < b.firstname ? -1 : 1;
})
James Andrews
sumber
itu lebih ringkas tetapi melanggar kontraknya: sign(f(a, b)) =-sign(f(b, a))(untuk a = b)
RiaD
3
return a.firstname == b.firstnameharus digunakan ===untuk kelengkapan
puiu
6

juga untuk penguraian asec dan desc, Anda dapat menggunakan ini: misalkan kita memiliki SortType variabel yang menentukan pengurutan atau pengurutan yang Anda inginkan:

 users.sort(function(a,b){
            return   sortType==="asc"? a.firstName.localeCompare( b.firstName): -( a.firstName.localeCompare(  b.firstName));
        })
ghazaleh javaheri
sumber
5

Fungsi umum dapat ditulis seperti di bawah ini

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

Anda dapat melewati parameter di bawah ini

  1. Data yang ingin Anda urutkan
  2. Properti dalam data olehnya harus disortir
  3. Parameter terakhir adalah tipe boolean. Ia memeriksa apakah Anda ingin menyortir dengan naik atau turun
Santosh
sumber
4

mencoba

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

Kamil Kiełczewski
sumber
2
fungsi sortir harus mengembalikan -1,0,1. ini hanya mengembalikan -1,1.
Radu Luncasu
@RaduLuncasu - dapatkah Anda memberikan data uji (array pengguna) yang menunjukkan bahwa solusi di atas memberikan hasil yang salah? (Sejauh yang saya tahu, kehilangan nol bukanlah masalah)
Kamil Kiełczewski
Jika fungsi perbandingan (a, b) mengembalikan 0, biarkan a dan b tidak berubah terhadap satu sama lain, tetapi diurutkan sehubungan dengan semua elemen yang berbeda.
Radu Luncasu
@ RaduLuncasu ok, tapi informasi itu tidak berarti nol wajib. Cara terbaik untuk menunjukkannya adalah menyiapkan data yang tidak berfungsi - tetapi sejauh yang saya tahu ini tidak mungkin - misalnya[9,8,7,6,5,1,2,3].sort((a,b) => a<b ? -1 : 1)
Kamil Kiełczewski
3

Anda dapat menggunakan ini untuk objek

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
sumber
2

hanya dengan kata-kata Anda dapat menggunakan metode ini

users.sort(function(a,b){return a.firstname < b.firstname ? -1 : 1});
FarukT
sumber
1

Anda dapat menggunakan metode larik bawaan - sort. Metode ini menggunakan metode panggilan balik sebagai param



    // 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"]


Poin-Poin Penting yang perlu diperhatikan untuk memahami kode ini.

  1. Metode kustom, dalam hal ini,, myCustomSortharus mengembalikan +1 atau -1 untuk setiap pasangan elemen (dari array input) perbandingan.
  2. Gunakan toLowerCase()/ toUpperCase()dalam metode panggilan balik penyortiran khusus sehingga perbedaan huruf besar / kecil tidak mempengaruhi kebenaran proses penyortiran.

Saya harap penjelasan ini cukup jelas. Jangan ragu untuk berkomentar jika menurut Anda, diperlukan lebih banyak info.

Bersulang!

shanky
sumber
Bukan jawaban yang tepat karena hanya melakukan kurang dari dan lebih besar dari cek dan bukan pemeriksaan yang sama.
Steel Brain
itu juga tidak membawa enything baru ke meja, dibandingkan dengan salah satu jawaban yang telah duduk di sana sejak ~ 2011.
amenthes
1

Dorong jawaban teratas menjadi prototipe untuk disortir berdasarkan kunci.

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
sumber
0

Anda dapat menggunakan sesuatu yang serupa, untuk menghilangkan case sensitif

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
sumber
7
Jawaban yang sama dengan yang dilakukan oleh Mrchief. Dengan kerugian lebih lanjut bahwa toLowerCase dilakukan empat kali per perbandingan, bukan dua kali.
amenthes
0

Implementasi saya, berfungsi baik di versi ES yang lebih lama:

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;
};
ekstrim
sumber
0

Sekadar catatan, jika Anda ingin memiliki fungsi sortir bernama, sintaksnya adalah sebagai berikut:

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

Perhatikan bahwa berikut ini TIDAK berfungsi:

users.sort(sortFunction(a,b))
Katinka Hesselink
sumber