Menyortir array objek di Ruby berdasarkan atribut objek?


129

Saya memiliki berbagai objek di Ruby on Rails. Saya ingin mengurutkan array berdasarkan atribut objek. Apa itu mungkin?

Jawaban:


223

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)

81
Atau versi singkatnya:objects.sort_by(&:attribute)
Nikola

3
objek yang lebih pendek.
sort_by

1
Jika Anda memiliki masalah dengan huruf besar & huruf kecil yang diurutkan secara terpisah, Anda dapat menggunakanobjects.sort_by { |obj| obj.attribute.downcase }
campeterson

1
Adakah yang tahu bagaimana hal ini dibandingkan sort!(misalnya kecepatan, dll.)?
Joshua Pinter


35

Ya, menggunakan Array#sort!ini mudah.

myarray.sort! { |a, b|  a.attribute <=> b.attribute }

Thnx buddy tetapi tidak berhasil bagi saya, saya memiliki berbagai objek. Di mana salah satu atribut dari objek tersebut adalah create_at. Saya ingin menyortirnya dengan bidang ini. jadi saya lakukan @ comm_bytes.sort! {| a, b | a.created_at <=> b.created_at} tapi tidak beruntung bagi saya, bisakah kamu membantu .... ??

4
Apakah ada metode create_at untuk mengakses atribut @created_at? Objek apa itu @created_at? Apakah itu mendefinisikan <=>? Jenis kesalahan apa yang Anda dapatkan? dll, dll, mual iklan. Dengan kata lain, kita membutuhkan lebih banyak detail daripada "tapi tidak beruntung bagi saya".
rampion

ini berfungsi jika Anda melakukan myarray = myarray.sort {...} tanpa "!"
DoruChidean

@Doru Ya, itu juga berhasil, tetapi mengapa Anda melakukan itu? Ini kurang langsung dan kurang efisien. Gunakan sortjika Anda ingin mempertahankan aslinya dan menetapkan hasilnya ke objek yang berbeda; jika tidak, gunakan varian di tempat sort!,. Faktanya, sortmemanggil secara sort!internal, setelah menyalin objek asli.
Konrad Rudolph

1
@Doru Pasti ada kesalahan di tempat lain dalam kode, saya bisa menjamin 100% Anda itu sort!akan bekerja dengan baik, dan selalu (!) Melakukan hal yang sama seperti yang Anda tulis.
Konrad Rudolph

27

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

20

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] }

14

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

10

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.


10

Lebih elegan objects.sort_by(&:attribute), Anda dapat menambahkan .reversejika Anda perlu mengganti urutan.



-2
@model_name.sort! { |a,b| a.attribute <=> b.attribute }

2
Ada banyak jawaban identik yang diposting pada tahun 2009. Tidak perlu menambahkan satu sama lain.
interjay

2
Jangan gunakan sortsaat 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.
Manusia Timah
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.