簡體   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