GROUP BY и агрегация по вектору карт - Clojure - PullRequest
9 голосов
/ 26 августа 2011

У меня есть данные, которые выглядят так:

(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}])

Я хочу сгруппировать по: firmAccount, а затем СУММИТЬ: Val и: PE для каждой учетной записи фирмы и получить что-то вроде

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

Это действительно тривиальная вещь, и в SQL я бы даже не подумал дважды, но, поскольку я изучаю clojure, пожалуйста, потерпите меня

Ответы [ 3 ]

8 голосов
/ 26 августа 2011

Clojure.core имеет встроенную функцию группировки. Решение становится немного уродливым из-за присутствия на картах как текста, так и значений.

(for [m (group-by :firmAccount a)]
   (assoc (apply merge-with + (map #(dissoc % :firmAccount) (val m)))
          :firmAccount (key m)))
6 голосов
/ 28 августа 2011

А для полноты вот альтернативная версия, которая использует карту:

(map (fn [[firmAccount vals]] 
   {:firmAccount firmAccount 
    :Val (reduce + (map :Val vals)) 
    :PE (reduce + (map :PE vals))}) 
  (group-by :firmAccount a))
1 голос
/ 26 августа 2011

Попробуйте создать новый массив карт или карту карт с такой же структурой.Вы можете написать функцию для добавления элементов к этой новой карте, которая суммирует эти поля, если существует: firm-account.Может быть, такая карта?

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

С персонализированной функцией добавления, например:

(add-to-map [element map]
  (if (contains? (find-name element))
    {map (add-fields element (find (find-name element)))}
    {map element}))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...