Saya memiliki berbagai objek di Ruby on Rails. Saya ingin mengurutkan array berdasarkan atribut objek. Apa itu mungkin?
Saya memiliki berbagai objek di Ruby on Rails. Saya ingin mengurutkan array berdasarkan atribut objek. Apa itu mungkin?
Jawaban:
Saya merekomendasikan menggunakan sort_by sebagai gantinya:
objects.sort_by {|obj| obj.attribute}
Apalagi jika atribut bisa dihitung.
Atau pendekatan yang lebih ringkas:
objects.sort_by(&:attribute)
objects.sort_by { |obj| obj.attribute.downcase }
sort!
(misalnya kecepatan, dll.)?
Ya, menggunakan Array#sort!
ini mudah.
myarray.sort! { |a, b| a.attribute <=> b.attribute }
<=>
? Jenis kesalahan apa yang Anda dapatkan? dll, dll, mual iklan. Dengan kata lain, kita membutuhkan lebih banyak detail daripada "tapi tidak beruntung bagi saya".
sort
jika Anda ingin mempertahankan aslinya dan menetapkan hasilnya ke objek yang berbeda; jika tidak, gunakan varian di tempat sort!
,. Faktanya, sort
memanggil secara sort!
internal, setelah menyalin objek asli.
sort!
akan bekerja dengan baik, dan selalu (!) Melakukan hal yang sama seperti yang Anda tulis.
Urutan menaik:
objects_array.sort! { |a, b| a.attribute <=> b.attribute }
atau
objects_array.sort_by{ |obj| obj.attribute }
Urutan menurun:
objects_array.sort! { |a, b| b.attribute <=> a.attribute }
atau
objects_array.sort_by{ |obj| obj.attribute }.reverse
jika Anda perlu mengurutkan berdasarkan dua atribut, di mana yang pertama lebih penting daripada yang kedua (berarti memperhitungkan argumen kedua hanya jika argumen pertama sama), maka Anda dapat melakukan seperti ini
myarray.sort{ |a,b| (a.attr1 == b.attr1) ? a.attr2 <=> b.attr2 : a.attr1 <=> b.attr1 }
atau dalam kasus array array
myarray.sort{ |a,b| (a[0] == b[0]) ? a[1] <=> b[1] : a[0] <=> b[0] }
Anda dapat membuat kelas apa pun dapat diurutkan dengan mengganti metode <=>:
class Person
attr_accessor :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
def <=>(other)
@last_name + @first_name <=> other.last_name + other.first_name
end
end
Sekarang array objek Person akan dapat diurutkan di last_name.
ar = [Person.new("Eric", "Cunningham"), Person.new("Homer", "Allen")]
puts ar # => [ "Eric Cunningham", "Homer Allen"] (Person objects!)
ar.sort!
puts ar # => [ "Homer Allen", "Eric Cunningham" ]
Array # sort berfungsi dengan baik, seperti yang diposting di atas:
myarray.sort! { |a, b| a.attribute <=> b.attribute }
TAPI, Anda perlu memastikan bahwa <=>
operator diimplementasikan untuk atribut itu. Jika itu adalah tipe data asli Ruby, ini bukan masalah. Jika tidak, tulis implementasi Anda sendiri yang mengembalikan -1 jika a <b, 0 jika sama, dan 1 jika a> b.
Lebih elegan objects.sort_by(&:attribute)
, Anda dapat menambahkan .reverse
jika Anda perlu mengganti urutan.
@model_name.sort! { |a,b| a.attribute <=> b.attribute }
sort
saat Anda mengurutkan objek yang tidak dapat dibandingkan secara langsung. Jika Anda harus mengakses atribut atau melakukan perhitungan untuk mendapatkan nilai yang akan dibandingkan, gunakan sort_by
. Ini akan jauh lebih cepat.
objects.sort_by(&:attribute)