2011-08-26 33 views
8

Tôi có dữ liệu mà trông như thế nàyGROUP BY và tập hợp trên Vector bản đồ - Clojure

(def a [{:firmAccount "MSFT" :Val 10 :PE 3 } 
{:firmAccount "MSFT" :Val 15 :PE 4} 
{:firmAccount "GOG" :Val 15 :PE 3} 
{:firmAccount "YAH" :Val 8 :PE 1}]) 

Tôi muốn nhóm bởi trên: firmAccount và sau đó tính tổng: Val và: PE cho mỗi tài khoản công ty và nhận được cái gì đó như

[{:firmAccount "MSFT" :Val 25 :PE 7} 
    {:firmAccount "GOG" :Val 15 :PE 3}  
    {:FirmAccount "YAH" :Val 8 :PE 1}] 

Nó thực sự là một điều tầm thường và trong SQL tôi sẽ thậm chí không nghĩ hai lần nhưng kể từ khi tôi đang học clojure xin vui lòng chịu với tôi

Trả lời

8

Clojure.core có một built-in nhóm theo chức năng. Các giải pháp trở nên xấu xí một chút bởi sự hiện diện của cả hai văn bản và int vals trong bản đồ.

(for [m (group-by :firmAccount a)] 
    (assoc (apply merge-with + (map #(dissoc % :firmAccount) (val m))) :firmAccount (key m))) 
+1

Cảm ơn rất nhiều. Nó hoạt động tốt cho tôi và nó rất ngắn gọn. Ngoài ra câu trả lời đã làm cho tôi nhận thức về cách sử dụng assoc, hợp nhất, áp dụng, phân tích, nhóm-by và bản đồ trong một ví dụ duy nhất mà là tuyệt vời. – Ash

1

Hãy thử tạo một mảng bản đồ mới hoặc bản đồ bản đồ với tương tự kết cấu. Bạn có thể viết một hàm để thêm các phần tử vào bản đồ mới này để tính tổng các trường nếu: tài khoản công ty tồn tại. Có lẽ một bản đồ như thế này?

(def a {"MSFT" {:Val 25 :PE 7 } 
    "GOG" {:Val 15 :PE 3} 
    "YAH" {:Val 8 :PE 1}}) 

Với add chức năng cá nhân như:

(add-to-map [element map] 
    (if (contains? (find-name element)) 
    {map (add-fields element (find (find-name element)))} 
    {map element})) 
+0

Vâng, nếu bạn sử dụng chức năng add tôi phác thảo ở đây bạn không cần phải thay đổi cấu trúc. Sử dụng ý tưởng này như thế nào bạn vui lòng. –

+0

Sự thay đổi là cần thiết do cơ sở hạ tầng trong câu hỏi. Cấu trúc bạn sử dụng trong câu trả lời là câu trả lời được yêu cầu, không phải là đầu vào được yêu cầu. – mac

5

Và cho đầy đủ đây là một phiên bản khác có sử dụng bản đồ:

(map (fn [[firmAccount vals]] 
    {:firmAccount firmAccount 
    :Val (reduce + (map :Val vals)) 
    :PE (reduce + (map :PE vals))}) 
    (group-by :firmAccount a)) 
+0

Thú vị, một. Cảm ơn rất nhiều – Ash