Этот код Clojure не является хорошим шаблоном для копирования: в нем много дублирования и мало объяснений того, что он делает.Я бы написал так:
(defn- organiseDataByTradeId [data]
(let [level-reader (fn [attr-list]
(let [levels (string/split attr-list #",")]
(fn [item]
(into {} (for [level levels]
[level (get item level)])))))
attr-levels (level-reader xmlLevelAttributesStr)
sub-levels (level-reader xmlSubLevelAttributesStr)]
(reduce (fn [acc item]
(update-in acc [(item "internaltradeid"),
(read-string (item "paramseqnum"))]
(fn [trade]
(-> trade
(assoc "levelcols" (attr-levels item))
(assoc-in ["subLevelCols", (read-string (item "cashflowseqnum"))]
(sub-levels item))))))
{}, data)))
Это больше строк кода, чем вашего оригинала, но я воспользовался возможностью назвать ряд полезных понятий и извлечь повторение в локальную функцию, чтобыэто самоочевидно.
Еще проще, если вы знаете, что не будет дублирования internaltradeid: вы можете просто сгенерировать несколько независимых карт и объединить их вместе:
(defn- organiseDataByTradeId [data]
(let [level-reader (fn [attr-list]
(let [levels (string/split attr-list #",")]
(fn [item]
(into {} (for [level levels]
[level (get item level)])))))
attr-levels (level-reader xmlLevelAttributesStr)
sub-levels (level-reader xmlSubLevelAttributesStr)]
(apply merge (for [item data]
{(item "internaltradeid")
{(read-string (item "paramseqnum"))
{"levelcols" (attr-levels item),
"subLevelCols" {(read-string (item "cashflowseqnum")) (sub-levels item)}}}}))))
Нона самом деле, ни один из этих подходов не будет работать в Scala, потому что у Scala иная философия моделирования данных, чем у Clojure.Clojure поощряет использование свободно определенных гетерогенных карт, таких как эта, где Scala предпочитает, чтобы ваши карты были однородными.Когда у вас будут данные, смешивающие несколько типов, Scala предлагает вам определить класс (или, возможно, класс кейсов - я не эксперт по Scala), а затем создать экземпляры этого класса.
Итак, здесь вы бы хотели Map[String, Map[Int, TradeInfo]]
, где TradeInfo
- это класс с двумя полями, levelcols : List[Attribute]
и subLevelCols
в качестве некоторой пары (или, возможно, одноэлементной карты)содержащий cashflowseqnum
и еще один List[Attribute]
.
После того, как вы смоделировали свои данные способом Scala, вы будете весьма далеки от использования всего, что выглядит как assoc-in
, потому что ваши данные выиграли 'это не одна гигантская карта, поэтому вопрос не возникнет.