[英]Is there an idiomatic way to find matching key and value in map in Clojure?
我正在嘗試從地圖中找到匹配的鍵和值對。 我正在使用以下代碼:
(defn matches? [m k v]
(let [val (k m)]
(= val v)))
my-demo.core=> (matches? {:a 1 :b 2} :b 2)
true
my-demo.core=> (matches? {:a 1 :b 2} :b 3)
false
使用superset?
另一種方法superset?
:
my-demo.core=> (superset? #{:a 1 :b 3} #{:a 1})
true
my-demo.core=> (superset? #{:a 1 :b 3} #{:a 2})
false
我覺得有一種更好的方法可以做到這一點。
我的問題是: 在Clojure中是否有一種慣用的方法可以在地圖中找到匹配的鍵和值?
這可能是一個小問題,你可以使用它而不是定義一個函數:
(= ({:a 1 :b 2} :a)
1)
=> true
我會說這是一種慣用的方式,對於大多數用例來說都可以正常工作。
但是,它取決於測試nil
值時所需的行為。 因為上面的方法會返回true
:c nil
:
(= ({:a 1 :b 2} :c)
nil)
=> true
並且您的函數的行為方式相同:
(matches? {:a 1 :b 2} :c nil)
=> true
為了解決這個問題,你可以使用get
了“未找到”值:
(= (get {:a 1 :b 2} :c ::not-found)
nil)
=> false
這工作正常,但它可能不是很整潔。 您只需要確保您的“未找到”值永遠不會與您的測試值相同。
如果你想真正知道一個地圖包含一個可能nil
值的密鑰,你將不得不檢查兩件事。 這是一個只執行一次哈希映射查找的函數。 它使用(find map key)
返回(find map key)
的映射條目(鍵值對),如果鍵不存在則返回nil。
(defn contains-kv? [m k v]
(if-let [kv (find m k)]
(= (val kv) v)
false))
(contains-kv? {:a 1 :b nil} :a 1)
=> true
(contains-kv? {:a 1 :b nil} :b nil)
=> true
(contains-kv? {:a 1 :b nil} :c nil)
=> false
注意:我不認為superset?
正在做你認為它做的事情。 在該示例中,您使用的是集合,而不是哈希映射,它們完全不同:
(clojure.set/superset? #{:a 1 :b 2} #{:a :b})
=> true
你的matches?
函數看起來不錯,雖然我可能會在這種情況下刪除let,因為它消除了一些混亂。 我還將它重命名為更精確的東西,盡管這是我現在能想到的最好的東西:
(defn contains-kv?
"Returns true if the key k is present in the given map m and it's value matches v."
[m k v]
(= (m k) v))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.