3

所以我有这个数据结构:

(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))

我如何使用新参数获得相同的结果?

4

2 回答 2

4

这里有三种方式:

;;; 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. 中的匿名函数中,partial在 2. 和 3. 中的最后一个函数中)以获取向量的向量而不是惰性序列的向量(从而使内部集合的构造变得非惰性——这可能很有意义)。

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

于 2013-05-26T02:06:03.267 回答
3

一种选择是使用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 []))
于 2013-05-26T12:53:41.997 回答