Clojure 检查地图上的键是否有值的惯用方法
检查地图上的键是否有值的惯用方法是什么?例如,如果我们有:Clojure 检查地图上的键是否有值的惯用方法,clojure,Clojure,检查地图上的键是否有值的惯用方法是什么?例如,如果我们有: => (def seq-of-maps [{:foo 1 :bar "hi"} {:foo 0 :bar "baz"}]) 要查找所有具有:foo==0的映射,我喜欢: => (filter (comp zero? :foo) seq-of-maps) ({:foo 0, :bar "baz"}) 但是如果我想找到所有带有:bar==“hi”的地图,我能想到的最好的方法是: => (filter #(= (:bar
=> (def seq-of-maps [{:foo 1 :bar "hi"} {:foo 0 :bar "baz"}])
要查找所有具有:foo==0的映射,我喜欢:
=> (filter (comp zero? :foo) seq-of-maps)
({:foo 0, :bar "baz"})
但是如果我想找到所有带有:bar==“hi”的地图,我能想到的最好的方法是:
=> (filter #(= (:bar %) "hi") seq-of-maps)
({:foo 1, :bar "hi"})
我觉得不太可读。有更好/更惯用的方法吗?惯用是主观的,但我会这么做
=> (filter (comp #{"hi"} :bar) seq-of-maps)
或者您所做的。您将匿名函数传递给筛选器的第三个示例似乎是查找具有给定值的映射的更为idomatic的方法之一。我发现它很容易阅读 clojure.set/index也可以在这里使用
((index seq-of-maps [:foo]) {:foo 0})
((index seq-of-maps [:bar]) {:bar "hi"})
如果需要,可以将其包装在函数中
(defn select-maps [xrel m]
((index xrel (keys m)) m))
然后
这两种方法都有效-您还可以使用索引ie请求具有多个键/值的映射:
(select-maps seq-of-maps {:foo 0 :bar "baz"})
选择包含foo 0和bar“baz”的所有贴图
正如佩皮恩所说,我认为惯用的方式因个人观点而异。
我有时使用
->
宏来提取嵌套的括号。我个人喜欢重构这种东西,以使用一个名称明确的高阶函数:
(def seq-of-maps [{:foo 1 :bar "hi"} {:foo 0 :bar "baz"}])
(defn has-value [key value]
"Returns a predicate that tests whether a map contains a specific value"
(fn [m]
(= value (m key))))
(filter (has-value :bar "hi") seq-of-maps)
=> ({:foo 1, :bar "hi"})
缺点是它为您提供了一个额外的函数定义来管理和维护,但我认为它的优雅性/代码可读性是值得的。如果多次重复使用谓词,从性能角度来看,这种方法也非常有效。我觉得您的代码很好。其他可能的解决方案是使用
for
宏,如下所示
(for [m seq-of-maps
:let [v (:bar m)]
:when (= v "hi")]
m)
只需将
zero?
替换为(partial=“hi”)
,如下所示:
=> (filter (comp (partial = "hi") :bar) seq-of-maps)
好主意,我喜欢。顺便说一句,在代码中,您的最终调用似乎与您在第一行中定义的
seq映射不匹配。考虑到这一点,这似乎无法获得您所需的确切行为,因为它将返回一组唯一映射的具体集,而不是可能包含重复映射的流。
(for [m seq-of-maps
:let [v (:bar m)]
:when (= v "hi")]
m)
=> (filter (comp (partial = "hi") :bar) seq-of-maps)