วิธีการจัดเรียง Ruby Hash ตามค่าตัวเลข?


154

ฉันมีเคาน์เตอร์แฮชที่ฉันพยายามเรียงลำดับตามจำนวน ปัญหาที่ฉันพบคือฟังก์ชัน Hash.sort ที่เป็นค่าเริ่มต้นเรียงลำดับหมายเลขเช่นสตริงแทนที่จะเป็นขนาดตัวเลข

เช่นได้รับกัญชา:

metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 10 }

ใช้รหัสนี้:

metrics.sort {|a1,a2| a2[1]<=>a1[1]}

จะส่งคืนอาร์เรย์ที่เรียงลำดับแล้ว:

[ 'siteb.com', 9, 'sitea.com', 745, 'sitec.com', 10]

แม้ว่า 745 จะเป็นตัวเลขที่มากกว่า 9 แต่ 9 จะปรากฏขึ้นเป็นลำดับแรกในรายการ เมื่อพยายามแสดงให้เห็นว่าใครมีค่าสูงสุดนี่ทำให้ชีวิตของฉันลำบาก :)

แนวคิดใด ๆ เกี่ยวกับวิธีเรียงลำดับแฮช (หรืออาร์เรย์) ตามขนาดค่าตัวเลข

ฉันขอขอบคุณความช่วยเหลือใด ๆ


คุณใช้ทับทิมรุ่นอะไร ผลการจัดเรียงของคุณแปลกมาก
fl00r

คำตอบ:


268

ไม่ทราบว่าคุณได้รับผลลัพธ์อย่างไรเนื่องจากจะไม่เรียงลำดับตามค่าสตริง ... คุณควรกลับรายการa1และa2ในตัวอย่างของคุณ

วิธีที่ดีที่สุดในกรณีใด ๆ (ตาม Mladen) คือ:

metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 10 }
metrics.sort_by {|_key, value| value}
  # ==> [["siteb.com", 9], ["sitec.com", 10], ["sitea.com", 745]]

หากคุณต้องการแฮชคุณสามารถใช้to_h(ใน Ruby 2.0+)

metrics.sort_by {|_key, value| value}.to_h
  # ==> {"siteb.com" => 9, "sitec.com" => 10, "sitea.com", 745}

84
หรือเพียงแค่sort_by{|k,v| v}
Mladen Jablanović

หมายเลขของฉันกลับมาเป็นสตริงที่แก้ไขได้ .. ฉันมี a2 และ a1 ตามลำดับเพราะฉันต้องการให้ผลลัพธ์เรียงลำดับ decending .. ขอบคุณสำหรับความคิดเห็นของคุณ
Dustin M.

นี่คือเหตุผลที่ฉันรัก Ruby ... ปัญหาเช่นนี้คือความเจ็บปวดในภาษาอื่น ง่ายมาก
Hady Elsahar

18
@Elchin: คุณสามารถใช้metrics.sort_by{ |k, v| v }.reverse.to_h
Marc-André Lafortune

4
ที่จริงแล้วเรียบง่ายกว่าด้วย: hash.sort_by (&: last) ที่มีข้อแม้แบบเดียวกันเกี่ยวกับการจับคู่ชุดกับ Hash
Gerry Gleason

84

เนื่องจาก value เป็นรายการสุดท้ายคุณสามารถ:

metrics.sort_by(&:last)

4
นี่มันเจ๋งมาก! referecne ใด ๆ สำหรับการกำหนดล่วงหน้าของ&:last?
Tamer Shlash

sort_by(&:last)มีการจดชวเลขอย่างมีประสิทธิภาพสำหรับsort_by {|x| x.last} stackoverflow.com/questions/1217088/…
Beni Cherniavsky-Paskin

14

ตอบแล้ว แต่ยังคง เปลี่ยนรหัสของคุณเป็น:

metrics.sort {|a1,a2| a2[1].to_i <=> a1[1].to_i }

แปลงเป็นสตริงตามทางหรือไม่สิ่งนี้จะทำงาน


9

นั่นไม่ใช่พฤติกรรมที่ฉันเห็น:

irb(main):001:0> metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" =>
 10 }
=> {"siteb.com"=>9, "sitec.com"=>10, "sitea.com"=>745}
irb(main):002:0> metrics.sort {|a1,a2| a2[1]<=>a1[1]}
=> [["sitea.com", 745], ["sitec.com", 10], ["siteb.com", 9]]

เป็นไปได้ไหมที่จะมีการแปลงตัวเลขของคุณเป็นสตริง? มีรหัสอื่นอีกหรือไม่ที่คุณไม่โพสต์


อ่าขวาของคุณมันดูเหมือนว่าผลลัพธ์ในรหัสของฉันกลับเป็นสตริง ประเภทข้อมูลที่น่าสงสัย :) บางครั้งฉันก็ใกล้กับปัญหามากเกินไป ขอบคุณ
Dustin M.

1
ได้. บางครั้งฉันได้ยินคนพูดถึงทับทิมว่า "ไม่พิมพ์" โอ้ไม่พิมพ์แน่นอน มันไม่ได้พิมพ์แบบคงที่ :)
Jacob Mattison
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.