【问题标题】:equivalent of assoc-in(clojure) in scala相当于 scala 中的 assoc-in(clojure)
【发布时间】:2019-05-01 05:11:21
【问题描述】:

我正在尝试在 scala 中找到等效的 assoc-in (clojure)。我正在尝试转换

(defn- organiseDataByTradeId [data]
(reduce #(let [a (assoc-in %1 
                        [(%2 "internaltradeid") (read-string (%2 "paramseqnum")) "levelcols"] 
                        (reduce (fn [m k](assoc m k (get %2 k))) 
                                {} 
                                (string/split xmlLevelAttributesStr #",")))
            b (assoc-in a



                      [(%2 "internaltradeid") (read-string (%2 "paramseqnum")) "subLevelCols" (read-string (%2 "cashflowseqnum"))]
                         (reduce (fn [m k] (assoc m k (get %2 k))) 
                                {} 
                                (string/split xmlSubLevelAttributesStr #","))               
                        )] 
            b)
      {}
      data))

到斯卡拉。 试过这个:

def organiseDataByTradeId(data: List[Map[String, String]]) = {
    data.map { entry => Map(entry("internaltradeid") -> Map(entry("paramseqnum").toInt -> Map("levelcols" -> (xmlLevelAttributesStr.split(",")).map{key=> (key,entry(key))}.toMap,
        "subLevelCols" -> Map(entry("cashflowseqnum").asInstanceOf[String].toInt -> (xmlSubLevelAttributesStr.split(",")).map{key=> (key,entry(key))}.toMap)))) }

  }

不确定如何在不覆盖的情况下合并我获得的地图列表。 这里 data List[Map[String,String]] 基本上是在描述一个表。每个条目是一行。列名是映射的键,值是值。xmlLevelAttributeStr 和 xmlSubLevelAttributeStr 是两个字符串,其中列名用逗号分隔。 我对斯卡拉相当陌生。我将每一行(Map [String,String])转换为scala Map,现在不知道如何合并它们,以便以前的数据不会被覆盖并且行为与clojure代码完全相同。我也不允许使用外部库,例如斯卡拉兹。

【问题讨论】:

  • 1.由于工作限制或面试要求,您不被允许? 2. 如果没有外部库,我要么将其拆分为多个函数,组合嵌套的mapflatMapupdated,要么实现我自己的TraversalOptional 光学。
  • 工作限制。我是 scala 的新手,因此不确定如何利用强大的模式匹配支持。我不确定我是否理解你所说的,你能否提供一个相同的示例实现?谢谢。

标签: scala dictionary merge clojure overwrite


【解决方案1】:

这个 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 作为某种包含@ 的对(或者可能是单元素映射) 987654327@ 和另一个List[Attribute]

一旦您以 Scala 方式对数据进行了建模,您就不会再使用类似于 assoc-in 的任何东西了,因为您的数据不会是一张巨大的地图,因此不会出现问题.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-22
    • 2021-05-09
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多