我试图从地图中找到匹配的键和值对。我使用以下代码:
(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?
的另一种方法:
my-demo.core=> (superset? #{:a 1 :b 3} #{:a 1})
true
my-demo.core=> (superset? #{:a 1 :b 3} #{:a 2})
false
我感觉有更好的方法可以做到这一点。
我的问题是:在Clojure中找到地图中的匹配键和值是否有惯用方法?
答案 0 :(得分:6)
这可能是一个小问题,您可以使用它而不是定义函数:
(= ({: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
和#34;未找到"值:
(= (get {:a 1 :b 2} :c ::not-found)
nil)
=> false
这种方法很好但可能不那么整洁。你只需要确保你没有找到""值与您的测试值永远不相同。
如果您想确实知道地图包含可能具有nil
值的密钥,则您必须检查这两项内容。这是一个只执行哈希映射查找一次的功能。它使用(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
答案 1 :(得分:2)
你的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))