2009-07-30 9 views
8

(Đây là một biến thể để this Q&A)Scala cách tốt nhất để chuyển Bộ sưu tập thành Bản đồ theo khóa? (2 biến thể)

Nói rằng tôi có điều này:

List("foo", "bar", "spam") 

Tôi muốn tạo ra một bản đồ mà chính là chiều dài của chuỗi và giá trị là Bộ sưu tập của tất cả các chuỗi có độ dài đó. Nói cách khác, được đưa ra danh sách về, chúng tôi nhận được:

Map(3 -> List(foo, bar), 4 -> List(spam)) 

Code tôi đã viết để làm điều này là:

list.foldLeft(Map[Long, List[String]]()) { 
    (m, s) => m(s.length) = s :: 
    (if (m.contains(s.length)) m(s.length) 
     else Nil) 
} 

này hoạt động, nhưng nó bổ sung thêm rất nhiều xấu xa để câu trả lời thanh lịch Daniel Spiewak cung cấp cho câu hỏi ban đầu (tham chiếu ở trên).

Bất kỳ ý tưởng nào về cách cải thiện giải pháp cho biến thể của tôi?

Cảm ơn! Sean

Trả lời

7

Nếu bạn không nhớ hiệu suất tệ hại:

val list = List("foo", "bar", "spam") 
val keyValue = for (length <- list map (_ length) removeDuplicates; 
        strings = list filter (_.length == length)) 
       yield (length -> strings) 
val map = Map(keyValue: _*) 

Vấn đề là danh sách được đọc một lần nữa cho mỗi chiều dài khác nhau.

Bây giờ, về uglyness của phiên bản của bạn, có lẽ đây sẽ giúp:

list.foldLeft(Map[Long, List[String]]()) { 
    (m, s) => m(s.length) = s :: m.getOrElse(s.length, Nil) 
} 

tốt hơn? Nó vẫn không khá tốt vì bạn có chiều dài gấp đôi. Cái này không có vấn đề này, nhưng nó hơi xấu xí:

list.foldLeft(Map[Long, List[String]]()) { 
    (m, s) => val length = s.length; m(length) = s :: m.getOrElse(length, Nil) 
} 
+0

Tôi không tìm thấy biến thể cuối cùng xấu xí, nếu độ dài val được rút ngắn thành val l. Biến thư đơn trong scala thường được sử dụng trong scala trong phong cách tương tự như các công thức toán học, tức là bạn khai báo ý nghĩa của một biến giữ chỗ, và sau đó chỉ cần sử dụng nó. Bởi vì điều này dẫn đến các biểu thức rất ngắn (thường là một lớp lót), tên ngắn được coi là khó hiểu trong các ngôn ngữ khác không phải là một vấn đề trong thực tế. – Palimondo

+0

@Palimondo Nó không phải là chiều dài làm phiền tôi. Tôi không thích phá vỡ tính toán trong hai câu lệnh. Thật không may, Scala không thể tối ưu hóa 's.length' để tái sử dụng giá trị, như Haskell sẽ làm. –

19

Với Scala 2.8.0:

list.groupBy(_.length) 

Nó không thể nhận được bất kỳ đơn giản hơn thế!

+0

Tôi nghĩ điều này rất thanh lịch, nhưng tôi không hiểu tại sao cần phải sắp xếp. Bạn có thể giải thích nó được không? Cảm ơn. – agilefall

+1

@agilefall: bạn nói đúng. sắp xếp là không cần thiết. cảm ơn! –