【问题标题】:clojure filter map by keysclojure 按键过滤映射
【发布时间】:2011-11-04 16:03:52
【问题描述】:

我正在关注这个例子:http://groups.google.com/group/clojure/browse_thread/thread/99b3d792b1d34b56

(见最后回复)

这是我得到的神秘错误:

Clojure 1.2.1
user=> (def m {:a "x" :b "y" :c "z" :d "w"})
#'user/m
user=> (filter #(some % [:a :b]) m)
java.lang.IllegalArgumentException: Key must be integer
(user=>

我也不明白为什么这会起作用。 (some ...) 不是每次都会返回第一个匹配值“x”吗?我是clojure的菜鸟,只是想学习。

请赐教。

【问题讨论】:

  • 您链接到的 ggroup 线程中的代码解决了一个不同的问题:“给定 一组 映射和一组键,返回给定的精确集合包含至少一个给定键的映射”。因此,在此代码中,filter 旨在对一组地图进行操作,而不是对单个地图进行操作;并且这个涉及some 的特定#(...) 块仅在给定映射不包含nilfalse 值时才适用(如线程中所述),但无论如何,它将应用它返回的函数(懒惰地)依次到每个给定的地图。
  • 好的,这解释了我的误解,谢谢。

标签: clojure


【解决方案1】:

我想我只是需要阅读更多文档:

(select-keys m [:a :b])

虽然我仍然不确定我找到的示例的意图是什么......

【讨论】:

    【解决方案2】:
    (filter 
      (fn [x] 
        (some #{(key x)} [:a :b])) m)
    

    使用filtersome 也会做同样的事情(但更丑更慢)。

    如果[:a :b] 在集合#{(key x)} 中(即使用集合作为谓词),则通过从m 过滤所有内容来工作,然后返回映射条目。

    【讨论】:

      【解决方案3】:

      如果您“迭代”地图,您将获得键值对而不是键。例如,

         user=> (map #(str %) {:a 1, :b 2, :c 3})
         ("[:a 1]" "[:b 2]" "[:c 3]")
      

      因此,您的匿名函数尝试评估 (some [:a "x"] [:a :b]),这显然不起作用。

      理想的解决方案是使用另一个答案中提到的select-keys

      【讨论】:

      • 只是一点点吹毛求疵:你可以说 (map str {:a 1 :b 2}) 稍微地道一点。 str 和 #(str %) 在功能上是等价的。
      猜你喜欢
      • 2016-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-09
      • 2021-08-13
      • 1970-01-01
      • 2019-02-02
      • 1970-01-01
      相关资源
      最近更新 更多