2009-06-21 43 views
10

Tôi đang học Scala và khám phá một số khía cạnh chức năng của ngôn ngữ.Giá trị danh sách tổng hợp ở Scala

Bắt đầu với danh sách các đối tượng có chứa hai tham số và tiền tệ thông số, làm cách nào tôi có thể tổng hợp tổng số tiền tệ cho mỗi loại tiền tệ?

//sample data 
val t1 = new Trade("T150310", 10000000, "GBP"); 
val t2 = new Trade("T150311", 10000000, "JPY"); 
val t3 = new Trade("T150312", 10000000, "USD"); 
val t4 = new Trade("T150313", 100, "JPY"); 
val t5 = new Trade("T150314", 1000, "GBP"); 
val t6 = new Trade("T150315", 10000, "USD"); 

val trades = List(t1, t2, t3, t4, t5, t6); 

Trả lời

4

Tôi đã viết một nhóm bằng cách đơn giản hoạt động (thực sự là một Groupabletrait với một chuyển đổi ngầm từ một Iterable) mà sẽ cho phép bạn nhóm các ngành nghề của bạn bằng cách currency của họ:

trait Groupable[V] extends Iterable[V] { 
    def groupBy(f: V => K): MultiMap[K, V] = { 
    val m = new mutable.HashMap[K, Set[V]] with mutable.MultiMap[K, V] 
    foreach { v => m add (f(v), v) } //add is defined in MultiMap 
    m 
    } 
} 
implicit def it2groupable(it: Iterable[V]): Groupable[V] = new Groupable[V] { 
    def elements = it.elements 
} 

Vì vậy Groupable là chỉ cần cung cấp một cách để trích xuất một khóa từ mỗi mục trong một Iterable và sau đó nhóm tất cả các mục đó có cùng khóa. Vì vậy, trong trường hợp của bạn:

//mm is a MultiMap[Currency, Trade] 
val mm = trades groupBy { _.currency } 

Bạn bây giờ có thể làm một khá đơn giản mapElements (mm là một Map) và một foldLeft (hoặc /: - cũng có giá trị hiểu biết các nhà điều hành foldLeft vì nó cho phép quy tụ rất ngắn gọn trên bộ sưu tập) để nhận số tiền:

val sums: Map[Currency, Int] = mm mapElements { ts => 
    (0 /: ts) { (sum,t) => sum + t.notional } 
} 

Xin lỗi nếu tôi đã mắc sai lầm trong dòng cuối cùng đó. ts là các giá trị của mm, tất cả là (tất nhiên) Iterable[Trade].

+0

Xin lỗi, vì một lý do nào đó tôi đã đọc "Giao dịch" nhưng đã nghe "Tuple" trong câu trả lời ban đầu của tôi. Tôi đã chỉnh sửa nó ngay bây giờ! –

16

Nếu bạn sử dụng thân cây, máy móc đã có sẵn. groupBy được xác định trên Traversable và tổng có thể được áp dụng trực tiếp vào danh sách, bạn không cần phải viết một lần.

scala> trades groupBy (_.currency) map { case (k,v) => k -> (v map (_.amount) sum) } 
res1: Iterable[(String, Int)] = List((GBP,10001000), (JPY,10000100), (USD,10010000)) 
+0

Có phải đó là phiên bản 2.8? –

+0

Và bạn có thể giải thích nơi hàm tổng hợp đến từ đâu không? –

+0

Có, thân cây là gì 2.8. Phương thức tổng được định nghĩa trên NumericTraversableOps - mà không phải là lớp bạn cần biết gì - nhưng về cơ bản nó thêm các phương thức vào Traversable bằng cách ngầm định dựa trên sự hiện diện của một số [T], mà chính nó định nghĩa "add" để tổng có thể được xác định chung. – extempore

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