2012-04-05 48 views
72

cách sắp xếp danh sách trong Scala theo hai trường, trong ví dụ này tôi sẽ sắp xếp theo lastName và firstName?Cách sắp xếp danh sách trong Scala theo hai trường?

case class Row(var firstName: String, var lastName: String, var city: String) 

var rows = List(new Row("Oscar", "Wilde", "London"), 
       new Row("Otto", "Swift", "Berlin"), 
       new Row("Carl", "Swift", "Paris"), 
       new Row("Hans", "Swift", "Dublin"), 
       new Row("Hugo", "Swift", "Sligo")) 

rows.sortBy(_.lastName) 

tôi thử những điều như thế này

rows.sortBy(_.lastName + _.firstName) 

nhưng nó không hoạt động. Vì vậy, tôi tò mò cho một giải pháp tốt và dễ dàng.

Trả lời

173
rows.sortBy(r => (r.lastName, r.firstName)) 
+4

điều gì xảy ra nếu chúng ta muốn đảo ngược sắp xếp trên lastName và sau đó sắp xếp tự nhiên trên firstName? –

+9

@SachinK: bạn phải tạo ra 'thứ tự' cho lớp 'Row' của riêng bạn và sử dụng nó với phương thức' sắp xếp' như sau: 'rows.sorted (customOrdering)'. Bạn cũng có thể sử dụng 'Ordering' tùy chỉnh cho' Tuple2' như sau: 'rows.sortBy (r => (r.lastName, r.firstName)) (Ordering.Tuple2 (Ordering.String.reverse, Ordering.String))' . – senia

+4

@SachinK: Bạn có thể thực hiện 'customOrdering' thành' Ordering [Row] 'theo cách thủ công hoặc sử dụng' Ordering.by' như sau: 'val customOrdering =' Ordering.by ((r: Row) => (r.lastName, r .firstName)) (Ordering.Tuple2 (Ordering.String.reverse, Ordering.String)) ' – senia

9
rows.sortBy (row => row.lastName + row.firstName) 

Nếu bạn muốn sắp xếp theo tên sáp nhập, như trong câu hỏi của bạn, hoặc

rows.sortBy (row => (row.lastName, row.firstName)) 

nếu bạn lần đầu tiên muốn sắp xếp theo lastName, sau đó firstName; có liên quan cho các tên dài hơn (Wild, Wilder, Wilderman).

Nếu bạn viết

rows.sortBy(_.lastName + _.firstName) 

với 2 gạch dưới, phương pháp này hy vọng hai tham số:

<console>:14: error: wrong number of parameters; expected = 1 
     rows.sortBy (_.lastName + _.firstName) 
          ^
+1

Thứ tự của điều này có thể sẽ không giống như sắp xếp theo tên, sau đó họ. – Marcin

+1

Cụ thể, khi tên cuối cùng có độ dài khác nhau –

+0

@Marcin: lastName, sau đó là firstName. Vâng bạn đã đúng. –

5

Nói chung, nếu bạn sử dụng một thuật toán sắp xếp ổn định, bạn có thể chỉ sắp xếp theo một chìa khóa, sau đó tiếp theo.

rows.sortBy(_.firstName).sortBy(_.lastName) 

Kết quả cuối cùng sẽ được sắp xếp theo họ, sau đó ở vị trí bằng nhau, theo tên.

+0

Bạn có chắc chắn rằng scala 'sortBy' sử dụng sắp xếp ổn định không? Nếu không câu trả lời này là vô nghĩa. –

+1

@ om-nom-nom: http://www.scala-lang.org/api/current/scala/util/Sorting$.html quickSort được xác định chỉ dành cho các loại giá trị, vì vậy có. – Marcin

+1

'hàng' là danh sách không thể thay đổi và' sortBy' trả về một giá trị mới thay vì thay đổi giá trị mà nó hoạt động (ngay cả trong các lớp có thể thay đổi). Vì vậy, biểu thức thứ hai của bạn chỉ là sắp xếp danh sách chưa được phân loại gốc. –

-4

Có lẽ công trình này chỉ dành cho một danh sách của Tuples, nhưng

scala> var zz = List((1, 0.1), (2, 0.5), (3, 0.6), (4, 0.3), (5, 0.1)) 
zz: List[(Int, Double)] = List((1,0.1), (2,0.5), (3,0.6), (4,0.3), (5,0.1)) 

scala> zz.sortBy(x => (-x._2, x._1)) 
res54: List[(Int, Double)] = List((3,0.6), (2,0.5), (4,0.3), (1,0.1), (5,0.1)) 

xuất hiện để làm việc và là một cách đơn giản để thể hiện nó.

+0

Nhưng không làm việc cho chuỗi, đó là những gì OP đang phân loại. –

+0

Câu hỏi này đã có một số câu trả lời nhận được tốt, không giới hạn trong danh sách các bộ dữ liệu. Vì vậy, lý do của việc đăng nó là gì? – honk

+0

@honk: Các giải pháp trước đây thực sự không hoạt động (AFAICT) trên Danh sách các bộ dữ liệu. Nếu tôi không phải là một newbie Scala, có lẽ tôi sẽ hiểu làm thế nào để morph những giải pháp trước để làm việc trong trường hợp đó, nhưng hôm nay tôi không. Tôi nghĩ rằng câu trả lời của tôi có thể giúp một người mới chơi Scala làm điều tương tự mà tôi đang cố gắng làm. – spreinhardt

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