การจัดเรียงอาร์เรย์ของวัตถุใน Ruby ตามแอตทริบิวต์ของวัตถุ?


คำตอบ:


224

ฉันแนะนำให้ใช้ sort_by แทน:

objects.sort_by {|obj| obj.attribute}

โดยเฉพาะอย่างยิ่งถ้าอาจมีการคำนวณแอตทริบิวต์

หรือแนวทางที่กระชับกว่านี้:

objects.sort_by(&:attribute)

81
หรือเวอร์ชันชวเลข:objects.sort_by(&:attribute)
Nikola

3
วัตถุที่สั้นกว่ามากขึ้นอีกต่อไป
short_by

1
หากคุณมีปัญหาเกี่ยวกับตัวพิมพ์ใหญ่และตัวพิมพ์เล็กที่ถูกจัดเรียงแยกกันคุณสามารถใช้ได้objects.sort_by { |obj| obj.attribute.downcase }
campeterson

1
มีความคิดอย่างไรเมื่อเปรียบเทียบกับsort!(เช่นความเร็ว ฯลฯ )
Joshua Pinter


35

ใช่การใช้Array#sort!สิ่งนี้เป็นเรื่องง่าย

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

เพื่อนขอบคุณ แต่มันไม่ได้ผลสำหรับฉันฉันมีวัตถุมากมาย ซึ่งหนึ่งในแอตทริบิวต์ของวัตถุถูกสร้าง _at ฉันต้องการจัดเรียงด้วยฟิลด์นี้ ดังนั้นฉันจึงทำ @ comm_bytes.sort! {| a, b | a.created_at <=> b.created_at} แต่ไม่มีโชคช่วยได้ไหม .... ??

4
มีวิธี created_at เพื่อเข้าถึงแอตทริบิวต์ @created_at หรือไม่ @created_at เป็นวัตถุประเภทใด มันกำหนด<=>? คุณได้รับข้อผิดพลาดประเภทใด ฯลฯ อาการคลื่นไส้โฆษณา กล่าวอีกนัยหนึ่งเราต้องการรายละเอียดมากกว่า "แต่ไม่มีโชคสำหรับฉัน"
rampion

ใช้งานได้ถ้าคุณทำ myarray = myarray.sort {... } โดยไม่มี "!"
DoruChidean

@ โดรุใช่นั่นได้ผลเหมือนกัน แต่ทำไมถึงทำแบบนั้นล่ะ? ตรงน้อยกว่าและมีประสิทธิภาพน้อยกว่า ใช้sortหากคุณต้องการรักษาต้นฉบับและกำหนดผลลัพธ์ให้กับวัตถุอื่น มิฉะนั้นให้ใช้ตัวแปรแทนที่, sort!. ในความเป็นจริงsortโทรsort!ภายในหลังจากคัดลอกวัตถุต้นฉบับ
Konrad Rudolph

1
@Doru ต้องมีข้อผิดพลาดที่อื่นในรหัสฉันสามารถรับประกันได้ 100% ว่าsort!จะใช้งานได้ดีและ (!) จะทำสิ่งเดียวกันกับที่คุณเขียนไว้เสมอ
Konrad Rudolph

27

ลำดับจากน้อยไปมาก:

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

หรือ

objects_array.sort_by{ |obj| obj.attribute }

ลำดับจากมากไปหาน้อย:

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

หรือ

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

20

ในกรณีที่คุณต้องการจัดเรียงตามแอตทริบิวต์สองรายการโดยที่หนึ่งมีความสำคัญมากกว่าอันดับที่สอง (หมายถึงการพิจารณาอาร์กิวเมนต์ที่สองเฉพาะในกรณีที่อาร์กิวเมนต์แรกเท่ากัน) คุณอาจทำเช่นนี้

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

หรือในกรณีของอาร์เรย์อาร์เรย์

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

14

คุณสามารถจัดเรียงคลาสใดก็ได้โดยการแทนที่ <=> วิธีการ:

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

ตอนนี้อาร์เรย์ของวัตถุบุคคลจะเรียงลำดับได้ใน 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 ทำงานได้ดีดังที่โพสต์ไว้ด้านบน:

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

แต่คุณต้องตรวจสอบให้แน่ใจว่าได้ใช้<=>ตัวดำเนินการสำหรับแอตทริบิวต์นั้น หากเป็นประเภทข้อมูลเนทีฟ Ruby ก็ไม่เป็นปัญหา มิฉะนั้นให้เขียนว่าคุณเป็นเจ้าของการนำไปใช้งานที่ส่งกลับค่า -1 ถ้า a <b, 0 ถ้ามันเท่ากันและ 1 if a> b




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

2
มีคำตอบที่เหมือนกันมากมายโพสต์ในปี 2009 ไม่จำเป็นต้องเพิ่มคำตอบอื่น
interjay

2
อย่าใช้sortเมื่อคุณจัดเรียงวัตถุที่ไม่สามารถเปรียบเทียบได้โดยตรง sort_byถ้าคุณมีคุณลักษณะการเข้าถึงหรือการทำการคำนวณที่จะได้รับความคุ้มค่าในการเปรียบเทียบการใช้งาน มันจะเร็วกว่ามาก
The Tin Man
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.