是否有一种干净,惯用的方法来检查地图的所有值是否为空或0.
例如,我有以下地图
{"id" 10 "Department" "UI Design" "managerid" 4}
Run Code Online (Sandbox Code Playgroud)
迭代映射值的最简洁方法是什么,并确保字符串不为空("")或nil,而int/long不是0或nil.
基本上我在尝试将其提交到数据库之前验证一些输入.我知道我可以使用像Prismatic/schema这样的库,但是现在我想知道如果没有它可以实现它.
此映射仅包含字符串和整数/长整数,但它可以包含其他类型.
有没有通用的方法这样做?
Multimethods可以为给定的问题提供优雅的解决方案:
; for now dispatch is based only on value type
(defmulti valid? (fn [[k v]] (class v)))
(defmethod valid? java.lang.Long [[_ value]] (not (zero? value)))
(defmethod valid? java.lang.String [[_ value]] (not (empty? value)))
(defmethod valid? nil [_] false)
(defmethod valid? :default [_] true) ; valid for rest cases
Run Code Online (Sandbox Code Playgroud)
要查看整个地图:
(every? valid? your-map)
Run Code Online (Sandbox Code Playgroud)
例子:
(every? valid? {:a 1 :b 0}) ; false
(every? valid? {:a 1 :b 1}) ; true
(every? valid? {:a 1 :b ""}) ; false
(every? valid? {:a 1 :b "a"}) ; true
(every? valid? {:a 1 :b "a" :c []}) ; true
Run Code Online (Sandbox Code Playgroud)
几点说明:
(not (empty? value))可以替换为(not-empty value)或(seq value),但在两种情况下都将返回字符串的完整值而不是布尔值(true当然仍将评估).nil因为nil它有自己的类型.在上面的示例中,所有nil值都被视为无效.如果对于某些键nils是可接受的 - (fn [[k v]] (class v))应该更改调度功能以考虑密钥.这个解决方案比简单的功能有点长
(defn valid? [[k v]]
(cond (string? v) (not (empty? v))
...
:else true))
Run Code Online (Sandbox Code Playgroud)
但它更易于维护和扩展.
编辑.正如评论中提到的,惯用的方式是用(seq coll)而不是(not (empty? coll))因为空?被定义为(not (seq coll)).您可能仍希望继续(not (empty? coll))检查以使验证代码更明确,更明显.