2015-11-23 31 views
2

鑑於集」替代重複使用的部分使用Clojure的`comp`

[{:key "key_1" :value "value_1"}, {:key "key_2" :value "value_2"}] 

的時候,我想將其轉換爲:

{"key_1" "value_1" "key_2" "value_2"} 

一個函數來完成,這將是:

(defn long->wide [xs] 
    (apply hash-map (flatten (map vals xs)))) 

我可以使用線程宏來簡化它:

(defn long->wide [xs] 
    (->> xs 
     (map vals) 
     (flatten) 
     (apply hash-map))) 

這仍然需要函數參數的明確定義,除了傳遞給第一個函數之外,我沒有做任何其他的事情。那麼我可能會重寫這個使用comp刪除此:

(def long->wide 
    (comp (partial apply hash-map) flatten (partial map vals))) 

然而,這需要重複使用的partial這對我來說是在功能的很大的噪音。

有Clojure中,結合comp->>,所以我可以創造一個更高階功能,無需重複使用的部分,也該出去不必創建一個新的功能的一些功能?

+2

如果你想要去的自由點,這將是一個選擇:'(部分爲{}(圖(juxt:鍵:值)))' – cfrick

+0

也'(瓦爾斯{:值「v1」:key「k1」})'(vs'(= {:value「v1」:key「k1」} {:key「k1」:value「v1」})')是危險的,沒有訂購(小的是「意外」) – cfrick

+0

@ cfrick的功能是可取的。如果你的數據顯示爲[{:value「value_1」:key「key_1」} {:value「value_2」,:key「key_2」}]',你的'(long-> wide data)'產生'{「 value_1「」key_1「,」value_2「」key_2「}'。謹防「扁平化」! – Thumbnail

回答

3

由於這裏的許多答案已經不回答原來的問題,但 提出了不同的方法,我也把這個答案也備份了。

我會去與減少和解構:

(reduce 
    (fn [m {:keys [key value]}] 
    (assoc m key value)) 
    {} 
    [{:key "key_1" :value "value_1"}, {:key "key_2" :value "value_2"}]) 

注意,這也將具有字符串鍵的工作(你在評論中提到)(注:strs):

(reduce 
     (fn [m {:strs [key value]}] 
     (assoc m key value)) 
     {} 
     [{"key" "key_1" "value" "value_1"}, {"key" "key_2" "value" "value_2"}]) 

使用關鍵字時的另一個(免費版)版本:

(partial (into {} (map (juxt :key :value)))) 

既然您提到評論,你正在使用數據庫中的值,也可能有機會,你可以切換到只返回值元組。然後,整個操作只需:

(into {} [["key_1" "value_1"]["key_2" "value_2"]]) 

還要注意,地圖和期待「插入順序」關於使用vals是 危險。小地圖是由事故只下令:

user=> (take 3 (zipmap (range 3) (range 3))) 
([0 0] [1 1] [2 2]) 
user=> (take 3 (zipmap (range 100) (range 100))) 
([0 0] [65 65] [70 70]) 
1

的其他替代不錯的答案也是:

(apply hash-map (mapcat vals [{:key "key_1" :value "value_1"}, {:key "key_2" :value "value_2"}])) 

或:

((comp #(apply hash-map %) #(mapcat vals %)) [{:key "key_1" :value "value_1"}, {:key "key_2" :value "value_2"}]) 

這是完全一樣的。

1

與clojure一樣,解決大多數問題的方法如此之多。

(partial #(reduce (fn [r m] (assoc r (m :key) (m :value))) 
        {} 
        %))) 

不知道如果匿名函數創建侵犯了您的條件或沒有,但這種不加入功能的命名空間,所以我想我會扔在那裏。這也有利於不要求輸入映射中的鍵爲關鍵字,因爲:由於映射處於功能位置,因此鍵和:值可以用任何類型的值替換。例如:

(partial #(reduce (fn [r m] (assoc r (m "key") (m "value"))) 
        {} 
        %)))