【问题标题】:Clojure, merging two array of mapsClojure,合并两个地图数组
【发布时间】:2012-04-18 12:17:28
【问题描述】:

我有两个地图数组

第一个是[{:a 1 :b 2 :d 6} {:a 2 :b 2} {:a 7 :b 7}]

第二个是[{:a 3 :c 3 :e 9 :y 7} {:a 2 :b 6 :c 8}]

取决于a 的值,即如果它在第二个数组中匹配,则“第二个地图”应该与“第一个地图”合并,并且生成的地图数组应该是

资源应该是[{:a 1 :b 2 :d 6} {:a 2 :b 6 :c 8} {:a 7 :b 7} {:a 3 :c 3 :e 9 :y 7}]

谁能帮我解决这个问题。提前致谢。

【问题讨论】:

  • 我不太确定算法是什么,换句话说,我不太确定你在比较什么来获得“Res”。
  • 我正在比较键“a”的值。如果第一个映射中的“a”的值与第二个数组中任何映射中的“a”的值匹配,则执行此操作(合并 {1st map with 'a' value = 1} {2nd map with 'a' value = 1 }) 并将这个结果映射添加到最终映射中

标签: clojure


【解决方案1】:

给你:

user> (def xs [{:a 1 :b 2 :d 6} {:a 2 :b 2} {:a 7 :b 7}])
#'user/xs
user> (def ys  [{:a 3 :c 3 :e 9 :y 7} {:a 2 :b 6 :c 8}])
#'user/ys
user> (for [[a ms] (group-by :a (concat xs ys))] (apply merge ms))
({:a 1, :b 2, :d 6} {:a 2, :c 8, :b 6} {:a 7, :b 7} {:y 7, :a 3, :c 3, :e 9})

【讨论】:

    【解决方案2】:

    这个数据结构在我看来非常笨拙,但这是我的看法:

    (defn key-by-a [coll]
      "Convert a list of maps to a map of maps keyed by their vals at :a"
      (apply hash-map (mapcat (juxt :a identity) coll)))
    
    (defn merge-map-lists [l1 l2]
      (->> [l1 l2]
        (map key-by-a)
        (apply merge-with merge)
        (vals)))
    

    它不做的一件事是维护输入列表的顺序,但由于不清楚哪个列表决定(两者可能具有不同顺序的相同键),所以我把它省略了。

    【讨论】:

      【解决方案3】:

      也许 clojure.set/join 是你想要的:

      这是clojure.set/join的文档:

      user=> (def animals #{{:name "betsy" :owner "brian" :kind "cow"}
                            {:name "jake"  :owner "brian" :kind "horse"}
                            {:name "josie" :owner "dawn"  :kind "cow"}})
      
      user=> (def personalities #{{:kind "cow" :personality "stoic"}
                                  {:kind "horse" :personality "skittish"}})
      #'user/personalities
      user=> (join animals personalities)
      
      #{{:owner "dawn",  :name "josie", :kind "cow",   :personality "stoic"}
        {:owner "brian", :name "betsy", :kind "cow",   :personality "stoic"}
        {:owner "brian", :name "jake",  :kind "horse", :personality "skittish"}}
      
      user=> (join animals personalities)
      #{{:kind "horse", :owner "brian", :name "jake", :species "cow", :personality "stoic"}
        {:kind "cow", :owner "dawn", :name "josie", :species "cow", :personality "stoic"}
        {:kind "horse", :owner "brian", :name "jake", :species "horse", :personality "skittish"}
        {:kind "cow", :owner "brian", :name "betsy", :species "cow", :personality "stoic"}
        {:kind "cow", :owner "dawn", :name "josie", :species "horse", :personality "skittish"}
        {:kind "cow", :owner "brian", :name "betsy", :species "horse", :personality "skittish"}}
      
      
      ;; Notice that "Jake" is both a horse and a cow in the first line. That's 
      ;; likely not what you want. You can tell `join` to only produce output 
      ;; where the `:kind` value is the same as the `:species` value like this:
      
      user=> (join animals personalities {:kind :species})
      #{{:kind "cow", :owner "dawn", :name "josie", :species "cow", :personality "stoic"}
        {:kind "horse", :owner "brian", :name "jake", :species "horse", :personality "skittish"}
        {:kind "cow", :owner "brian", :name "betsy", :species "cow", :personality "stoic"}}
      

      【讨论】:

        猜你喜欢
        • 2023-03-16
        • 2020-05-27
        • 1970-01-01
        • 2012-03-21
        • 2019-12-22
        • 1970-01-01
        • 2012-02-06
        • 1970-01-01
        相关资源
        最近更新 更多