2012-01-17 25 views
20

Tôi có một mảng mulitdimensional như vậy:Sorting: Sắp xếp mảng dựa trên nhiều điều kiện trong Ruby

[ 
    [name, age, date, gender] 
    [name, age, date, gender] 
    [..] 
] 

Tôi đang tự hỏi là cách tốt nhất để sắp xếp mảng này dựa trên nhiều điều kiện ... Ví dụ, làm thế nào tôi có sắp xếp dựa theo số tuổitrước tiên sau đó theo tên không?

tôi đã rối tung xung quanh với các phương pháp sort như vậy:

array.sort { |a,b| [ a[1], a[0] ] <=> [ b[1], b[0] ] } 

Bên cạnh đó tôi không thực sự hiểu cú pháp này, tôi không nhận được kết quả tôi mong đợi. Tôi có nên sử dụng phương pháp sort không? Tôi có nên so sánh kết quả riêng lẻ theo mapping mảng không?

+1

có thể trùng lặp [Sắp xếp tập hợp các đối tượng theo số (cao nhất trước) rồi theo chữ cái (chữ cái)] (http: // stackoverflow.com/questions/2232470/sort-a-collection-of-objects-by-number-highest-first-then-by-letter-alphabeti) –

+1

@pruett: không thiếu tôn trọng câu trả lời của robbrit, nhưng bạn nên cân nhắc lựa chọn câu trả lời, không có gì sai với việc sử dụng Enumerable # sort * trừ * khi Enumerable # sort_by thực hiện công việc. Điều này có thể gây hiểu lầm cho những người hạ cánh ở đây. – tokland

+0

Có thể trùng lặp [Ruby sắp xếp theo nhiều giá trị?] (Http://stackoverflow.com/questions/4309723/ruby-sort-by-multiple-values) – jtbandes

Trả lời

39

Bạn nên luôn luôn sử dụng sort_by để sắp xếp khóa. Không chỉ dễ đọc hơn, nó còn là nhiều hơn hiệu quả hơn. Ngoài ra, tôi cũng muốn sử dụng ràng buộc phá hủy, một lần nữa, để dễ đọc:

ary.sort_by {|name, age| [age, name] } 
+3

[binducturing bind] (http://stackoverflow.com/a/3952057/38765) –

11

này nên làm như lừa:

array.sort { |a,b| [ a[1], a[0] ] <=> [ b[1], b[0] ] } 

Vậy điều này làm gì? Nó sử dụng rất nhiều thành ngữ Ruby.

  • Đầu tiên là các khối, giống như gọi lại hoặc các hàm/lớp ẩn danh bằng các ngôn ngữ khác. Phương thức của Array sort sử dụng chúng để so sánh hai phần tử dựa trên giá trị trả về của khối. Bạn có thể đọc tất cả về chúng here.
  • Tiếp theo là nhà điều hành <=>. Nó trả về -1 nếu đối số đầu tiên nhỏ hơn giá trị thứ hai, 0 nếu chúng bằng nhau và 1 nếu giá trị đầu tiên lớn hơn giá trị thứ hai. Khi bạn sử dụng nó với mảng, nó sẽ so sánh các mảng yếu tố khôn ngoan cho đến khi một trong số chúng trả về -1 hoặc 1. Nếu các mảng bằng nhau, bạn sẽ nhận được 0.
+0

giải thích tuyệt vời ... nhờ @robbrit. – pruett

+6

Bạn cũng có thể sử dụng 'sort_by {| a | [a [1], a [0]]} ', việc xây dựng tất cả các mảng đó không đến miễn phí. –

6

Khi tôi hiểu nó bạn muốn đặt hàng theo độ tuổi đầu tiên, và sau đó nếu nhiều hơn một bản ghi có cùng độ tuổi, hãy sắp xếp tập hợp con theo tên.


này làm việc cho tôi

people = [ 
     ["bob", 15, "male"], 
     ["alice", 25, "female"], 
     ["bob", 56, "male"], 
     ["dave", 45, "male"], 
     ["alice", 56, "female"], 
     ["adam", 15, "male"] 
    ] 

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

# The sorted array is 

[["adam", 15, "male"], 
["bob", 15, "male"], 
["alice", 25, "female"], 
["dave", 45, "male"], 
["alice", 56, "female"], 
["bob", 56, "male"]] 

Điều này đang làm là so sánh theo độ tuổi đầu tiên, và nếu tuổi là như nhau (< => returs 0) nó so sánh tên.

+0

rất đẹp! tôi thích cú pháp đó – pruett

+0

nếu tuổi là như nhau và sau đó chúng tôi muốn sắp xếp tên theo thứ tự giảm dần? – inquisitive

+0

@Inquisitive sau đó trong trường hợp đó tôi nghĩ rằng bạn sẽ chuyển đổi "a" và "b" trong "(a [1] <=> b [1])" ở bên phải. – user1515295

Các vấn đề liên quan