繁体   English   中英

如何在Clojure中对向量的向量进行迭代?

[英]How do I iterate over a vector of vectors in Clojure?

我有一条带有3个属性的消息:类型,货币和金额。

我有一个带有4个属性的规则,一个目标,一个消息类型,一种货币和一个数量。

我想检查规则,找到与消息类型匹配的消息并返回目标,如果没有匹配,则返回null

我将矢量用于消息和规则中字段的固定位置,它们的定义如下:

user=> (def msg [100, "USD", 100])
#’user/msg

user=> (def rules [["FAL" 100 "UKP" 100] ["FBC" 101 "USD" 100]])
#’user/rules

然后定义一些从规则和消息中提取消息类型的函数:

user=>(defn rule-mt [[_ mt]] mt)
#’user/rule-mt

user=>(defn msg-mt [[mt]] mt)
#’user/msg-mt

我定义了一个函数来匹配消息类型,如下所示:

user=>(defn match-mt [ msg rule ] ( = ( rule-mt rule ) ( msg-mt msg ) ) )
#’user/match-mt

因此,我可以按以下方式直接调用它来检查它是否与第一个规则匹配:

user=>(match-mt msg (rules 0))
true

然后查看它是否与第二条规则匹配:

(match-mt msg (rules 1))
false

如何遍历调用匹配函数的规则(向量的向量),然后返回匹配规则的目标字段(规则的第一个字段)?

去做就对了! 这是一个解决方案,它使用for查找与消息匹配的所有规则,然后使用first返回它们中的first 但是,由于懒惰,仅需要计算一次成功的匹配。

(defn dest-of-rule [rule] (first rule))
(defn get-dest [msg]
   (first
      (for [r rules
            :when (match-mt msg r)]
         (dest-of-rule r))))

这是使用过滤器执行相同操作的替代解决方案:

(defn get-dest [msg]
   (dest-of-rule (first (filter #(match-mt msg %) rules))))

first + filter用法很常见,这就是为什么有一个名字的原因: find-first 它可以在seq-utils包中找到( 请参阅此处 )。

为什么使用向量而不是地图作为数据类型有特定原因吗? 我认为,通过使用地图,您可以摆脱助手功能,并生成更具可读性的代码。

这是我的处理方式:

(def msg {:type 100 :currency "USD" :amount 100})
(def rules [{:destination "FAL" :type 100 :currency "UKP" :amount 100}
            {:destination "FBC" :type 101 :currency "USD" :amount 100}])

match-mt函数将变为:

(defn match-mt [msg rule] (= (:type msg) (:type rule)))

要获取第一个匹配规则的目的地(类似于opqdonut提供的答案):

(defn get-dest [msg]
  (:destination (first (filter (partial match-mt msg) rules))))

您还可以编写一个泛型函数来检查两个(或多个)输入的某个字段是否相等,并根据此定义get-est:

(defn field= [key & inputs]
  (apply = (map key inputs)))
(defn get-dest [msg]
  (:destination (first (filter (partial field= :type msg) rules))))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM