Ruby'deki bir dizi nesneyi nesne özelliğine göre mi sıralıyorsunuz?


129

Ruby on Rails'de bir dizi nesnem var. Diziyi nesnenin bir özelliğine göre sıralamak istiyorum. Mümkün mü?

Yanıtlar:


223

Bunun yerine sort_by kullanmanızı öneririm:

objects.sort_by {|obj| obj.attribute}

Özellikle öznitelik hesaplanabiliyorsa.

Veya daha özlü bir yaklaşım:

objects.sort_by(&:attribute)

81
Veya kısa versiyon:objects.sort_by(&:attribute)
Nikola

3
daha da kısa nesneler.sort_by &: attribute
jasin_89

1
Büyük ve küçük harflerin ayrı ayrı sıralanmasıyla ilgili sorun yaşıyorsanız, şunu kullanabilirsiniz:objects.sort_by { |obj| obj.attribute.downcase }
campeterson

1
Bunun nasıl karşılaştırıldığı hakkında bir fikriniz var mı sort!(örneğin hız, vb.)?
Joshua Pinter


35

Evet, bunu kullanmak Array#sort!çok kolay.

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

Thnx dostum ama benim için işe yaramadı bir dizi nesnem var. Nesnenin özniteliğinden hangisinin yaratıldığı_at. Bu alanla sıralamak istiyorum. bu yüzden @ comm_bytes.sort yaptım! {| a, b | a.created_at <=> b.created_at} ama benim için şans yok, yardımcı olabilir misiniz .... ??

4
@Created_at özniteliğine erişmek için bir created_at yöntemi var mı? @Created_at ne tür bir nesnedir? Tanımlıyor mu <=>? Ne tür hatalar alıyorsun? vb, vb, ve mide bulantısı. Başka bir deyişle, "ama benim için şans yok" dan daha fazla ayrıntıya ihtiyacımız var.
rampion

myarray = myarray.sort {...} "!" olmadan yaparsanız çalışır.
DoruChidean

@Doru Evet, bu da işe yarıyor, ama bunu neden yaptın? Daha az doğrudan ve daha az verimli. sortOrijinali korumak ve sonucu farklı bir nesneye atamak istiyorsanız kullanın ; aksi takdirde, yerinde varyantı kullanın sort!. Aslında, orijinal nesneyi kopyaladıktan sonra dahili olarak sortarama yapar sort!.
Konrad Rudolph

1
@Doru Kodun başka bir yerinde bir hata olmalı, size% 100 sort!iyi çalışacağını garanti edebilirim ve her zaman (!) Yazdıklarınızla aynı şeyi yapın.
Konrad Rudolph

27

Artan sıra:

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

veya

objects_array.sort_by{ |obj| obj.attribute }

Azalan sipariş :

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

veya

objects_array.sort_by{ |obj| obj.attribute }.reverse

20

iki özniteliğe göre sıralamanız gerekirse, burada birincisi daha önemli, sonra ikincisi (ikinci argümanları yalnızca ilk argümanlar eşitse hesaba katmak anlamına gelir), o zaman bunu yapabilirsiniz

myarray.sort{ |a,b| (a.attr1 == b.attr1) ? a.attr2 <=> b.attr2 : a.attr1 <=> b.attr1 }

veya dizi dizisi durumunda

myarray.sort{ |a,b| (a[0] == b[0]) ? a[1] <=> b[1] : a[0] <=> b[0] }

14

<=> yöntemini geçersiz kılarak herhangi bir sınıfı sıralanabilir hale getirebilirsiniz:

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

Artık bir dizi Person nesnesi last_name üzerinde sıralanabilir.

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

Dizi # sıralaması, yukarıda yayınlandığı gibi iyi çalışır:

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

ANCAK, <=>operatörün bu öznitelik için uygulandığından emin olmanız gerekir . Ruby yerel veri türüyse, bu bir sorun değildir. Aksi takdirde, a <b ise -1, eşitse 0 ve a> b ise 1 döndüren kendi uygulamanızı yazın.


10

Daha zarif objects.sort_by(&:attribute), .reversesiparişi değiştirmeniz gerekirse bir de ekleyebilirsiniz .



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

2
2009'da yayınlanan pek çok özdeş cevap var. Başka bir tane eklemeye gerek yok.
interjay

2
sortDoğrudan karşılaştırılamayan nesneleri sıralarken kullanmayın . Özniteliklere erişmeniz veya bir hesaplama yapmanız gerekiyorsa, değeri karşılaştırmak için kullanın sort_by. Çok daha hızlı olacak.
The Tin Man
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.