【问题标题】:How to get the same vals in a more flatten data-structure in Clojure?如何在 Clojure 中以更扁平的数据结构获得相同的 val?
【发布时间】:2013-05-26 01:37:11
【问题描述】:

所以我有这个数据结构:

(def params
  {:site1
    {:index-element
       {:date  "2012-10-10"
        :title "Hello"}
     :subpage-element
        {:time     "9:00"
         :location "Toronto"}}
   :site2 …})

我想把它改成更扁平的数据结构

(def new-params  
  {1
    {:name     :site1
     :date     ["2012-10-10" :index-element]
     :title    ["Hello"      :index-element] 
     :time     ["9:00"       :subpage-element]
     :location ["Toronto"    :subpage-element]}
   2 …})

为了得到我想要的结果:

(mapv #(-> params % :index-element vals)
      (keys params))

如何使用 new-params 获得相同的结果?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    这里有三种方法:

    ;;; 1.
    (reduce-kv (fn [res siteno m]
                 (->> (vals m)
                      (filter #(and (vector? %)
                                    (identical? :index-element (peek %))))
                      (map first)
                      (conj res)))
               []
               new-params)
    
    ;;; 2.
    (->> new-params
         (vals)
         (map vals)
         (map (partial filter #(and (vector? %)
                                    (identical? :index-element (peek %)))))
         (mapv (partial map first)))
    
    ;;; 3. (better than 2., but only for Clojure >= 1.5)
    (require '[clojure.core.reducers :as r])
    
    (->> new-params
         (vals)
         (r/map vals)
         (r/map (partial filter #(and (vector? %)
                                      (identical? :index-element (peek %)))))
         (r/map (partial map first))
         (into []))
    

    切换到mapv(在 1. 中的匿名函数中,在 2. 和 3. 中的最后一个 partial 中)以获取向量向量而不是惰性序列向量(从而构建内部集合非惰性——这可能很有意义)。

    原来的数据结构其实更适合这种访问;无法避免使用更平坦的地图进行线性搜索。这可能是一个性能问题,具体取决于访问模式和实际数据。

    【讨论】:

    • 好帖子,谢谢!我真的很惊讶它是如此复杂。我想你是对的,尽管扁平化地图往往更干净,但在这种情况下,取回与 :index-element 关联的 val 会变得更加复杂。
    【解决方案2】:

    一种选择是使用for(在恕我直言,这使它更具可读性):

    (->> (for [[i site] new-params]
           (for [ [s-k s-v] site
                  :when (not= s-k :name)
                  :let [[k [v v-k]] [s-k s-v]]
                  :when (= v-k :index-element)]
             v))
         (into []))
    

    【讨论】:

      猜你喜欢
      • 2019-09-06
      • 1970-01-01
      • 2017-01-07
      • 2017-04-22
      • 2017-04-17
      • 2012-08-10
      • 2021-08-21
      • 1970-01-01
      • 2021-11-19
      相关资源
      最近更新 更多