首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用clj-schema来验证一个映射序列是否具有给定键的唯一值。

使用clj-schema来验证一个映射序列是否具有给定键的唯一值。
EN

Stack Overflow用户
提问于 2014-04-28 11:18:24
回答 1查看 366关注 0票数 0

我有一个请求对象,它包含一系列映射。我想验证在这些映射中,给定的键没有重复的值。

例如,这是有效的:

代码语言:javascript
复制
[
  { :id 1, :data "foo" }
  { :id 2, :data "bar" }
]

这是无效的,因为它包含:id 1的副本。

代码语言:javascript
复制
[
  { :id 1, :data "foo" }
  { :id 2, :data "bar" }
  { :id 1, :data "baz" }
]

目前,我有一些类似于:

代码语言:javascript
复制
(def-map-schema item-schema
                [[:id] integer?
                 [:data] string?])

(def-map-schema request-schema
                [[:items] (sequence-of item-schema)])

如何使用clj-schema表示此唯一性约束?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-04-28 12:18:50

clj-架构提供了一个函数clj-schema.schema/simple-schema,可用于将任意谓词转换为架构.下面是如何使用它实现maps-with-unique-key?模式:

代码语言:javascript
复制
(defn maps-with-unique-key? [k]
  (s/simple-schema [(s/sequence-of map?)
                    (fn [xs]
                      (= (count xs)
                         (count (distinct (map #(get % k) xs)))))]))

在REPL会议上:

代码语言:javascript
复制
(v/valid? (maps-with-unique-key? :id)
          [])
;= true
(v/valid? (maps-with-unique-key? :id)
          [{:id 0 :foo "bar"} {:id 1 :foo "baz"} {:id 2 :foo "quux"}])
;= true
(v/valid? (maps-with-unique-key? :id)
          [{:id 0 :foo "bar"} {:id 1 :foo "baz"} {:id 0 :foo "quux"}])
;= false
(v/valid? (maps-with-unique-key? :id)
          [["not a map"] {:id 0 :foo "bar"} {:id 1 :foo "baz"} {:id 2 :foo "quux"}])
;= false

(下面是我对棱镜模式的最初答案。)

我不认为在标准模式发行版中有现成的模式,但是总是可以实现一个新的模式--参见模式的wiki中的定义新模式类型页面。

这是一个草图:

代码语言:javascript
复制
(defrecord MapsWithUniqueKey [k]
  s/Schema
  (walker [this]
    (fn [x]
      (if (and (or (seq? x) (vector? x))
               (every? map? x)
               (every? #(contains? % k) x)
               (== (count x)
                   (count (distinct (map #(get % k) x)))))
        x
        (schema.macros/validation-error
         this x
         (list 'maps-with-unique-key? k (schema.utils/value-name x))))))
  (explain [this]
    (list 'maps-with-unique-key? k)))

示例验证:

代码语言:javascript
复制
(s/check (->MapsWithUniqueKey :id)
         [{:id 1 :foo "bar"} {:id 2 :foo "baz"} {:id 3 :foo "quux"}])
;= nil
(s/check (->MapsWithUniqueKey :id)
         [{:id 1 :foo "bar"} {:id 2 :foo "baz"} {:id 1 :foo "quux"}])
;= (not (maps-with-unique-key? :id a-clojure.lang.PersistentVector))

从第一个调用返回的nil表示成功,而后者返回的值是一个schema.utils.ValidationError

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23339695

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档