Я пытаюсь объединить ключи карты, основанные на сходстве значения ключа, чтобы создать новую карту с ключевыми значениями, подобными объединенным в один. Ниже мой код, чтобы проиллюстрировать свои идеи:Clojure: Идиоматический способ слияния клавиш карты на основе сходства клавиш?
Учитывая набор данных:
(def engineer-visits (incanter.core/dataset ["Engineer" "Credit" "Comments"]
[
["Jonah" 1 "OK"]
["Jonah" 2 "Very good"]
["Joneh" 0 "Not very good"]
["Joneh" 3 "Excellent"]
["Esther" 2 "Missing comment"]
["Esther" 4 "Extraordinary"]
]
))
со значением:
| Engineer | Credit | Comments |
|----------+--------+-----------------|
| Jonah | 1 | OK |
| Jonah | 2 | Very good |
| Joneh | 0 | Not very good |
| Joneh | 3 | Excellent |
| Esther | 2 | Missing comment |
| Esther | 4 | Extraordinary |
Следующая производит карту от инженера до его/ее записи:
(def by-engineers (incanter.core/$group-by "Engineer" engineer-visits))
со значением:
{{"Engineer" "Jonah"}
| Engineer | Credit | Comments |
|----------+--------+-----------|
| Jonah | 1 | OK |
| Jonah | 2 | Very good |
, {"Engineer" "Joneh"}
| Engineer | Credit | Comments |
|----------+--------+---------------|
| Joneh | 0 | Not very good |
| Joneh | 3 | Excellent |
, {"Engineer" "Esther"}
| Engineer | Credit | Comments |
|----------+--------+-----------------|
| Esther | 2 | Missing comment |
| Esther | 4 | Extraordinary |
}
С помощью следующей функции, я хотел бы получить:
(map-merged-by-key-value-similarity by-engineers 0.8)
{{"Engineer" "Jonah"}
| Engineer | Credit | Comments |
|----------+--------+---------------|
| Jonah | 1 | OK |
| Jonah | 2 | Very good |
| Joneh | 0 | Not very good |
| Joneh | 3 | Excellent |
, {"Engineer" "Esther"}
| Engineer | Credit | Comments |
|----------+--------+-----------------|
| Esther | 2 | Missing comment |
| Esther | 4 | Extraordinary |
}
(defn map-merged-by-key-value-similarity
"From a map produced by $gorup-by on a datasest, produce a map of the same structure, with key column values merged by similarity."
[a-map threshold]
(let [
column-keys (keys a-map)
key-column-name (->> column-keys
first
keys
first)
;; Deconstruct the key column values from the key of the map, i.e. the pair of column name and column value:
key-column-values (flatten (map vals column-keys))
;; Compute string clusters for the values:
value-simularity-cluster (similarity-cluster key-column-values threshold)
;; Reconstruct the key for the updated map from the clustered column values:
reconstructed-column-value-key-cluster-list (map (fn [cluster]
(map (fn [name]
{key-column-name name})
cluster))
value-simularity-cluster)
representative (fn [cluster] (first cluster)) ; out of a cluster
map-from-cluster-combined-fn (fn [cluster]
; the cluster is a list of maps from key-column-mane to string of the column's value
(if (< 1 (count cluster))
;; combine
(apply merge-with conj-rows (map (fn [key]
{(representative cluster) (a-map key)})
cluster))
;; as is
{(first cluster) (a-map (first cluster))}
))
]
(apply merge (map map-from-cluster-combined-fn reconstructed-column-value-key-cluster-list))
)
)
выше функция действительно работает, как ожидалось. Я хотел бы более идиоматический способ добиться этого. Поскольку существует довольно симметрийный процесс разложения ключа и ценности карты, обработки на клавишах и восстановления обратной подобной карты, я чувствую, что ее можно было бы более красноречиво сделать. Я смутно помню, что в Scala некоторые операторы Mondard могут быть полезны для доступа и обработки информации, глубоко погруженной в структуру списка.
Спасибо за ваш комментарий или помощь!
Примечание: similarity-cluster
преобразует список строк в список списка строк, где аналогичные строки помещаются в закрытый список. Это моя реализация. Подробности здесь не имеют отношения к моему вопросу.
Пожалуйста, попробуйте представить более изолированный случай, иллюстрирующий проблему. –