Saya memiliki berbagai objek JavaScript:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
Bagaimana saya bisa mengurutkannya berdasarkan nilai last_nom
dalam JavaScript?
Saya tahu sort(a,b)
, tapi itu hanya bekerja pada string dan angka. Apakah saya perlu menambahkan toString()
metode ke objek saya?
javascript
arrays
sorting
Tyrone Slothrop
sumber
sumber
Jawaban:
Cukup mudah untuk menulis fungsi perbandingan Anda sendiri:
Atau sebaris (c / o Marco Demaio):
sumber
return a.last_nom.localeCompare(b.last_nom)
akan bekerja juga.return a.value - b.value;
(ASC)localeCompare
penting ketika menggunakan karakter beraksen dalam bahasa asing, dan lebih elegan juga.Anda juga bisa membuat fungsi sortir dinamis yang mengurutkan objek berdasarkan nilainya yang Anda berikan:
Jadi Anda dapat memiliki berbagai objek seperti ini:
... dan itu akan berfungsi ketika Anda melakukannya:
Sebenarnya ini sudah menjawab pertanyaan. Bagian di bawah ini ditulis karena banyak orang menghubungi saya, mengeluh bahwa itu tidak berfungsi dengan beberapa parameter .
Beberapa parameter
Anda dapat menggunakan fungsi di bawah ini untuk menghasilkan fungsi sortir dengan beberapa parameter sortir.
Yang memungkinkan Anda melakukan hal seperti ini:
Array subkelas
Untuk yang beruntung di antara kita yang dapat menggunakan ES6, yang memungkinkan memperluas objek asli:
Itu akan memungkinkan ini:
sumber
dynamicSort()
pada contoh di atas akan menempatkan huruf besar di depan huruf kecil. Sebagai contoh, jika saya memiliki nilai-nilaiAPd
,Aklin
danAbe
- hasil dalam ASC semacam harusAbe
,Aklin
,APd
. Tapi dengan contoh Anda, hasilnyaAPd
,Abe
,Aklin
. Pokoknya untuk memperbaiki perilaku ini?var result = a[property].localeCompare(b[property]);
bukanvar 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]);
Di ES6 / ES2015 atau yang lebih baru, Anda dapat melakukan ini:
Sebelum ke ES6 / ES2015
sumber
last_nom
menggunakan hanya nomor dalam array:1
?objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom, undefined, {numberic: true}));
underscore.js
gunakan garis bawah, kecil dan mengagumkan ...
sumber
var sortedObjs = _.sortBy( objs, 'first_nom' );
,.objs
akan tidak diurutkan dirinya sebagai hasil dari ini. Fungsi akan mengembalikan array yang diurutkan. Itu akan membuatnya lebih eksplisit.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
bagi mereka yang lebih suka yangvar sortedObjs = _.sortBy( objs, 'first_nom' );
atau jika Anda menginginkannya dalam urutan yang berbeda:var sortedObjs = _.orderBy( objs, ['first_nom'],['dsc'] );
Jangan mengerti mengapa orang membuatnya begitu rumit:
Untuk mesin yang lebih ketat:
Tukar operator untuk mengaturnya berdasarkan urutan abjad terbalik.
sumber
if(a.count == b.count) return a.name > b.name; else return a.count > b.count;
Jika Anda memiliki nama belakang yang sama, Anda bisa mengurutkannya berdasarkan nama depan-
sumber
b
harus muncul setelaha
dalam array. Jika angka positif dikembalikan, itu berartia
harus datang setelahb
. Jika0
dikembalikan, itu berarti mereka dianggap sama. Anda selalu dapat membaca dokumentasi: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…1, 0, -1
sebelum saya bertanya di sini. Saya hanya tidak menemukan info yang saya butuhkan.Solusi sederhana dan cepat untuk masalah ini menggunakan pewarisan prototipe:
Contoh / Penggunaan
Pembaruan: Tidak lagi memodifikasi array asli.
sumber
Pada 2018 ada solusi yang jauh lebih pendek dan elegan. Gunakan saja. Array.prototype.sort () .
Contoh:
sumber
a.value - b.value
digunakan untuk membandingkan atribut objek ( nomor dalam kasus ini) dapat diadopsi untuk berbagai waktu data. Misalnya, regex dapat digunakan untuk membandingkan setiap pasangan dari string yang berdekatan .Jawaban lama yang tidak benar:
MEMPERBARUI
Dari komentar Beauchamp:
Format yang lebih mudah dibaca:
Tanpa terary bersarang:
Penjelasan:
Number()
akan dilemparkantrue
ke1
danfalse
ke0
.sumber
arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))
Alih-alih menggunakan fungsi perbandingan kustom, Anda juga bisa membuat tipe objek dengan
toString()
metode kustom (yang dipanggil oleh fungsi perbandingan default):sumber
Lodash.js (superset dari Underscore.js )
Adalah baik untuk tidak menambahkan kerangka kerja untuk setiap bagian sederhana dari logika, tetapi mengandalkan kerangka kerja utilitas yang teruji dapat mempercepat pengembangan dan mengurangi jumlah bug.
Lodash menghasilkan kode yang sangat bersih dan mempromosikan pemrograman yang lebih fungsional gaya . Dalam sekejap menjadi jelas apa maksud dari kode tersebut.
Masalah OP dapat dengan mudah dipecahkan sebagai:
Info lebih lanjut? Misalnya kita memiliki objek bersarang berikut:
Kita sekarang dapat menggunakan singkatan _.property
user.age
untuk menentukan jalur ke properti yang harus dicocokkan. Kami akan mengurutkan objek pengguna berdasarkan properti umur bersarang. Ya, ini memungkinkan pencocokan properti bersarang!Ingin dibalik? Tidak masalah. Gunakan _.reverse .
Ingin menggabungkan keduanya menggunakan rantai ?
Atau kapan Anda lebih suka mengalir dari rantai
sumber
Kamu bisa menggunakan
Cara termudah: Lodash
( https://lodash.com/docs/4.17.10#orderBy )
Metode ini seperti _.sortBy kecuali bahwa itu memungkinkan menentukan urutan perintah dari iterate untuk mengurutkan berdasarkan. Jika pesanan tidak ditentukan, semua nilai diurutkan dalam urutan naik. Kalau tidak, tentukan urutan "desc" untuk turun atau "asc" untuk urutan urutan naik dari nilai yang sesuai.
Argumen
koleksi (Array | Objek): Koleksi untuk beralih. [iteratees = [_. identity]] (Array [] | Function [] | Object [] | string []): The iteratees untuk mengurutkan berdasarkan. [order] (string []): Urutan pesanan iteratees.
Kembali
(Array): Mengembalikan array yang diurutkan baru.
sumber
Ada banyak jawaban bagus di sini, tetapi saya ingin menunjukkan bahwa mereka dapat diperluas sangat sederhana untuk mencapai penyortiran yang jauh lebih kompleks. Satu-satunya hal yang harus Anda lakukan adalah menggunakan operator OR untuk rantai fungsi perbandingan seperti ini:
Di mana
fn1
,,fn2
... adalah fungsi sortir yang mengembalikan [-1,0,1]. Ini menghasilkan "sorting by fn1", "sorting by fn2" yang hampir sama dengan ORDER BY dalam SQL.Solusi ini didasarkan pada perilaku
||
operator yang mengevaluasi ekspresi pertama yang dievaluasi yang dapat dikonversi menjadi true .Bentuk paling sederhana hanya memiliki satu fungsi inline seperti ini:
Dengan dua langkah
last_nom
,first_nom
urutan akan terlihat seperti ini:Fungsi perbandingan generik bisa jadi seperti ini:
Fungsi ini dapat diperluas untuk mendukung bidang angka, sensitivitas huruf, tipe data arbiter, dll.
Anda dapat mereka menggunakannya dengan merantai mereka dengan mengurutkan prioritas:
Intinya di sini adalah bahwa JavaScript murni dengan pendekatan fungsional dapat membawa Anda jauh tanpa perpustakaan eksternal atau kode kompleks. Ini juga sangat efektif, karena tidak ada parsing string yang harus dilakukan
sumber
Contoh penggunaan:
Naskah:
sumber
1, 0, -1
digunakan untuk pemesanan semacam. Bahkan dengan penjelasan Anda di atas, yang terlihat sangat bagus - saya masih belum mengerti. Saya selalu berpikir-1
ketika menggunakan properti panjang array, yaitu:arr.length = -1
berarti item tidak ditemukan. Saya mungkin mencampuradukkan hal-hal di sini, tetapi bisakah Anda membantu saya memahami mengapa angka1, 0, -1
digunakan untuk menentukan urutan? Terima kasih.a
danb
, jikaa
lebih besar darib
tambahkan 1 ke indeksa
dan letakkan di belakangb
, jikaa
kurang darib
, kurangi 1 daria
dan letakkan di depanb
. Jikaa
danb
sama, tambahkan 0 kea
dan biarkan di tempatnya.Saya belum melihat pendekatan khusus ini disarankan, jadi inilah metode perbandingan singkat yang saya suka gunakan yang bekerja untuk keduanya
string
dannumber
:Berikut penjelasan tentang
sortBy()
:sortBy()
menerima afn
yang memilih nilai apa dari objek untuk digunakan sebagai perbandingan, dan mengembalikan fungsi yang dapat diteruskan langsung keArray.prototype.sort()
. Dalam contoh ini, kami menggunakano.last_nom
sebagai nilai untuk perbandingan, jadi setiap kali kami menerima dua objek melaluiArray.prototype.sort()
sepertidan
kita gunakan
untuk membandingkannya.
Mengingat itu
fn = o => o.last_nom
, kita dapat memperluas fungsi bandingkan ke yang setaraOR logis
||
memiliki fungsi hubungan arus pendek yang sangat berguna di sini. Karena cara kerjanya, fungsi tubuh di atas berartiSebagai bonus tambahan, inilah yang setara di ECMAScript 5 tanpa fungsi panah, yang sayangnya lebih bertele-tele:
sumber
Saya tahu pertanyaan ini terlalu lama, tetapi saya tidak melihat implementasi yang serupa dengan saya.
Versi ini didasarkan pada idiom transformasi Schwartzian .
Berikut ini contoh cara menggunakannya:
sumber
Menyortir (lebih banyak) Susunan Kompleks Objek
Karena Anda mungkin menemukan struktur data yang lebih kompleks seperti array ini, saya akan memperluas solusinya.
TL; DR
Masalah
Saya menemukan di bawah dan tidak bisa mengubahnya. Saya juga tidak ingin meratakan objek untuk sementara waktu. Saya juga tidak ingin menggunakan garis bawah / lodash, terutama karena alasan kinerja dan kesenangan untuk mengimplementasikannya sendiri.
Tujuan
Tujuannya adalah untuk mengurutkannya berdasarkan
People.Name.name
dan olehPeople.Name.surname
Rintangan
Sekarang, dalam solusi dasar menggunakan notasi braket untuk menghitung properti untuk mengurutkan secara dinamis. Namun, di sini, kita harus membuat notasi braket secara dinamis, karena Anda akan mengharapkannya
People['Name.name']
berfungsi - yang tidak.Cukup melakukan
People['Name']['name']
, di sisi lain, bersifat statis dan hanya memungkinkan Anda untuk turun n ke tingkat .Larutan
Penambahan utama di sini adalah berjalan menyusuri objek pohon dan menentukan nilai daun terakhir, Anda harus menentukan, serta setiap daun perantara.
Contoh
Contoh kerja di JSBin
sumber
Satu opsi lagi:
macam naik secara default.
sumber
Fungsi sederhana yang mengurutkan array objek berdasarkan properti
Pemakaian:
sumber
Cara sederhana:
Lihat itu
'.toLowerCase()'
perlu untuk mencegah erro dalam membandingkan string.sumber
objs.sort( (a,b) => b.last_nom.toLowerCase() < a.last_nom.toLowerCase() );
tambahan desc params untuk kode Ege Özcan
sumber
Menggabungkan solusi dinamis Ege dengan ide Vinay, Anda mendapatkan solusi tangguh yang bagus:
Pemakaian:
sumber
Berdasarkan contoh Anda, Anda perlu mengurutkan berdasarkan dua bidang (nama belakang, nama depan), bukan satu. Anda bisa menggunakan pustaka Alasql untuk membuat ini dalam satu baris:
Coba contoh ini di jsFiddle .
sumber
sumber
Diberikan contoh asli:
Urutkan berdasarkan beberapa bidang:
Catatan
a.localeCompare(b)
adalah universal didukung dan kembali -1,0,1 jikaa<b
,a==b
,a>b
masing-masing.||
di baris terakhir memberilast_nom
prioritas lebihfirst_nom
.var age_order = left.age - right.age;
return -last_nom_order || -first_nom_order || -age_order;
sumber
Coba ini,
sumber
Anda mungkin perlu mengubahnya menjadi huruf kecil untuk mencegah kebingungan.
sumber
sumber
Menggunakan Ramda,
npm pasang ramda
sumber
Ini adalah masalah yang sederhana, tidak tahu mengapa orang memiliki solusi yang begitu rumit.
Fungsi sortir sederhana (berdasarkan algoritma sortir cepat):
Gunakan contoh:
sumber