2017-05-19 267 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}