2017-05-19 491 views
2

說我有一個地圖m{"good1" 1, "bad1" 1, "good2" 2, "bad2" 2},我想基於一些謂詞在地圖鍵刪除條目,要做到這一點的一種方式是:刪除鍵

(defn dissoc-by [f m] (->> m (filter (complement f)) (into {}))) 
(dissoc-by #(.contains (first %1) "bad") m) 
=> {"good1" 1, "good2" 2} 

有沒有更clojure這樣做的習慣方法?

回答

4

這是一個非常正常的方式去做,有一個校正,即來自一個映射的序列是一個pair [鍵值]序列,而不僅僅是鍵,所以你的過濾器函數需要明確地使用該鍵

user> (defn dissoc-by [f m] (->> m (filter #(f (first %))) (into {}))) 
#'user/dissoc-by 
user> (dissoc-by #(.contains % "good") m) 
{"good1" 1, "good2" 2} 

如果你想獲得幻想它和use a transducer這個功能可以通過消除分配給數據從一個步驟到下一個移動的中間序列更有效率。

user> (defn dissoc-by [f m] 
     (into {} (filter #(f (first %))) m)) 
#'user/dissoc-by 
user> (dissoc-by #(.contains % "good") m) 
{"good1" 1, "good2" 2} 

into有一個可選的中間參數,換能器的功能,即可以過濾或因爲它傾入收集轉換數據。

+1

良好的漁獲!我剛剛也注意到了這一點,但也許決定一個更一般的解決方案是將鍵值對傳遞給謂詞。我也意識到,函數的命名約定意味着謂詞應該刪除,而不是保留元素。 – user12341234

+0

是的,那在問題的方式以及。 [sic] –

+0

選擇匹配輸入還是輸出呃? –

5

鑑於

(def data {"good1" 1, "bad1" 1, "good2" 2, "bad2" 2}) 

限定

(defn remove-keys [pred m] 
    (apply dissoc m (filter pred (keys m)))) 

然後

(remove-keys #(string/includes? % "bad") data) 
=> {"good1" 1, "good2" 2} 

類似的功能在The Clojure Cookbook在/定義。

0

這裏是不正是你所需要的代碼:

(def data {"good1" 1, "bad1" 1, "good2" 2, "bad2" 2}) 

(into (empty data) 
     (filter (fn [[k v]] (clojure.string/includes? k "good")) 
       data)) 

{"good1" 1, "good2" 2}