Saya memiliki serangkaian string yang harus saya sortir dalam JavaScript, tetapi dengan cara case-insensitive. Bagaimana cara melakukan ini?
javascript
sorting
case-insensitive
Jérôme Verstrynge
sumber
sumber
return a.localeCompare(b, 'en', {'sensitivity': 'base'});
toLowerCase()
ketikalocaleCompare
sudah melakukannya secara default dalam beberapa kasus. Anda dapat membaca lebih lanjut tentang parameter untuk diteruskan ke sini: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…items.sort(new Intl.Collator('en').compare)
untuk kinerja yang lebih baik. (Lihat MDN .)EDIT: Harap dicatat bahwa saya awalnya menulis ini untuk menggambarkan teknik daripada memiliki kinerja dalam pikiran. Lihat juga jawaban @Ivan Krechetov untuk solusi yang lebih ringkas.
sumber
toLowerCase
dua kali pada setiap string; akan lebih efisien untuk menyimpan versi yang lebih rendah dari string dalam variabel..toLowerCase()
beberapa kali untuk setiap item dalam array. Misalnya, 45 panggilan ke fungsi bandingkan saat mengurutkan 10 item dalam urutan terbalik.var i = 0; ["z","y","x","w","v","u","t","s","r","q"].sort(function (a, b) {++i; return a.toLowerCase().localeCompare(b.toLowerCase());}); console.log("Calls to Compare: " + i); // i === 45
Inilah saatnya untuk meninjau kembali pertanyaan lama ini.
Anda sebaiknya tidak menggunakan solusi yang diandalkan
toLowerCase
. Mereka tidak efisien dan tidak berfungsi dalam beberapa bahasa (Turki misalnya). Lebih suka ini:Periksa dokumentasi untuk kompatibilitas browser dan semua yang perlu diketahui tentang
sensitivity
opsi ini.sumber
sumber
return a === b ? 0 : a > b ? 1 : -1;
["111", "33"]
, kita mungkin ingin mengembalikannya["111", "33"]
karena 1 datang sebelum 3 dalam urutan kode karakter. Namun, fungsi dalam jawaban ini akan kembali["33", "111"]
karena angkanya33
kurang dari angkanya111
."33" > "111" === true
dan33 > 111 === false
. Ini berfungsi sebagaimana dimaksud.Anda juga dapat menggunakan yang baru
Intl.Collator().compare
, per MDN itu lebih efisien saat menyortir array. Kelemahannya adalah tidak didukung oleh peramban lama. MDN menyatakan bahwa itu tidak didukung sama sekali di Safari. Perlu memverifikasinya, karena menyatakan yangIntl.Collator
didukung.sumber
Jika Anda ingin menjamin urutan yang sama terlepas dari urutan elemen dalam larik input, berikut adalah penyortiran yang stabil :
sumber
Normalisasi kasus
.sort()
dengan.toLowerCase()
.sumber
Anda juga dapat menggunakan operator Elvis:
Memberi:
Metode localeCompare mungkin baik-baik saja ...
Catatan: Operator Elvis adalah bentuk pendek 'operator ternary' karena jika demikian, biasanya dengan penugasan.
Jika Anda melihat?: Sideways, sepertinya Elvis ...
yaitu bukannya:
kamu bisa memakai:
yaitu ketika y benar, maka kembalikan 1 (untuk penugasan ke x), jika tidak kembalikan 2 (untuk penugasan ke x).
sumber
x = y ? y : z
, Anda dapat melakukannyax = y ?: z
. Javascript tidak memiliki operator Elvis yang sebenarnya, tetapi Anda dapat menggunakannyax = y || z
dengan cara yang serupa.Jawaban lain mengasumsikan bahwa array berisi string. Metode saya lebih baik, karena akan berfungsi walaupun array mengandung null, undefined, atau non-string.
The
null
akan diurutkan antara 'nulk' dan 'nulm'. Tetapiundefined
akan selalu diurutkan terakhir.sumber
(''+notdefined) === "undefined"
jadi itu akan mengurutkan sebelum "z"Array.prototype.sort
: | karena bagian tentang(''+notdefined) === "undefined"
benar - benar benar ... yang berarti jika Anda membalik -1 dan 1 dalam fungsi sortir untuk membalik urutan, undefined masih menyortir sampai akhir. Itu juga perlu dipertimbangkan ketika menggunakan fungsi perbandingan di luar konteks semacam array (seperti ketika saya menemukan pertanyaan ini).Array.prototype.sort
definisi itu - beberapa komentar lagi. Pertama, tidak perlu untuk(''+a)
-toString()
script ECMAS perlu dipanggil pada elemen sebelum meneruskannya ke compareFn. Kedua, fakta yangignoreCase
kembali1
ketika membandingkan string yang sama (termasuk string yang sama tetapi untuk kasus) berarti spesifikasi tidak menentukan hasil jika ada nilai duplikat (mungkin akan baik-baik saja hanya dengan beberapa swap yang tidak perlu terjadi, saya pikir).undefined
adalah kasus khusus, yang untuk x x <undefined dan x> undefined keduanya salah . Ituundefined
selalu yang terakhir, adalah produk sampingan dari implementasi semacam sort. Saya mencoba mengubah ('' a) menjadi sekadar, tetapi gagal. saya mengertiTypeError: a.toUpperCase is not a function
. TernyatatoString
ini tidak disebut sebelum menelepon compareFn.undefined
perbandinganFn tidak pernah disebutVersi ES6:
["Foo", "bar"].sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }))
Sumber: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
sumber
Untuk mendukung jawaban yang diterima saya ingin menambahkan bahwa fungsi di bawah ini tampaknya mengubah nilai-nilai dalam array asli untuk diurutkan sehingga tidak hanya akan mengurutkan huruf kecil tetapi nilai huruf besar juga akan diubah menjadi huruf kecil. Ini adalah masalah bagi saya karena meskipun saya ingin melihat Mary di sebelah Maria, saya tidak berharap bahwa kasus nilai pertama Mary diubah menjadi huruf kecil.
Dalam percobaan saya, fungsi berikut dari jawaban yang diterima mengurutkan dengan benar tetapi tidak mengubah nilai.
sumber
Ini dapat membantu jika Anda kesulitan memahami:
http://jsfiddle.net/ianjamieson/wmxn2ram/1/
sumber
Dalam fungsi di atas, jika kita hanya membandingkan ketika huruf kecil dua nilai a dan b, kita tidak akan mendapatkan hasil yang cantik.
Contoh, jika array adalah [A, a, B, b, c, C, D, d, e, E] dan kami menggunakan fungsi di atas, kami memiliki persis array itu. Itu tidak mengubah apa pun.
Agar hasilnya adalah [A, a, B, b, C, c, D, d, E, e], kita harus membandingkan lagi ketika dua nilai huruf kecil sama:
sumber
Saya membungkus jawaban teratas dalam polyfill sehingga saya bisa memanggil .sortIgnoreCase () pada array string
sumber
Bungkus string Anda
/ /i
. Ini adalah cara mudah menggunakan regex untuk mengabaikan casingsumber