2013-05-26 58 views
3

所以我有這樣的數據結構:如何在Clojure中的更扁平數據結構中獲得相同的值?

(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 & 3.在1匿名函數,在最後partial

;;; 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得到載體的載體,而不是懶惰的載體seqs(從而使內部集合的構建非懶惰 - 這很有意義)。

原始數據結構實際上更適合這種訪問;有沒有避免用平坦的地圖進行線性搜索。這可能是性能問題,具體取決於訪問模式和實際數據。

+0

偉大的職位,謝謝!我真的很驚訝,這是複雜的。我想你是對的,即使flatten貼圖趨向於更乾淨,在這種情況下,返回與index-element關聯的val會更加複雜。 – leontalbot

+0

@ user1184248:使用'for'使其更加清晰 – Ankur

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 [])) 
相關問題