dictionary - 如何在 Clojure 中正确“过滤”映射?
问题描述
我一直在使用 Clojure 玩了一段时间,但我陷入了我认为对许多人来说非常微不足道的事情……但不是我。我有以下代码;
;; Define a Record structure
(defrecord Person [first-name last-name age occupation])
(def john (->Person "John" "Frusciante" 50 "Guitarist"))
;; People map
(def people {"1" john
"2" (->Person "Pablo" "Neruda" 90 "Poet")
"3" (->Person "Stefan" "Zweig" 120 "Author")
}
)
(defn get-120-year-old-guy
[peeps]
(filter #(= (:age %) 120) peeps)
)
(println "who's 120?: " (get-120-year-old-guy people))
此调用返回一个空列表。我知道我检索值的方式有问题,但看不到究竟是什么。
解决方案
您可以通过临时更改函数来了解正在发生的事情:
(defn get-120-year-old-guy
[peeps]
(filter (fn [m] (println (type m) m)) peeps))
印刷:
(clojure.lang.MapEntry [1 #user.Person{:first-name John, :last-name Frusciante, :age 50, :occupation Guitarist}]
clojure.lang.MapEntry [2 #user.Person{:first-name Pablo, :last-name Neruda, :age 90, :occupation Poet}]
clojure.lang.MapEntry [3 #user.Person{:first-name Stefan, :last-name Zweig, :age 120, :occupation Author}]
)
注意每个条目是一个MapEntry
. 在您的尝试中,您正在申请:age
整个MapEntry
(返回nil
),而不仅仅是人。
我认为使用完整的匿名函数进行解构是最简单的方法:
(defn get-120-year-old-guy
[peeps]
(filter (fn [[_ person]] (= (:age person) 120)) peeps))
输出:
who's 120?: ([3 #user.Person{:first-name Stefan, :last-name Zweig, :age 120, :occupation Author}])
@leetwinski 指出了一个更惯用的解决方案,它完全取消了显式函数:
(filter (comp #{120} :age val) people)
分解:
(defn get-120-year-old-guy [peeps]
(filter (comp ; And (comp)ose all three checks together
#{120} ; Then test if it's in the set of #{120}
:age ; Then get the age
val) ; Get the value from the MapEntry
peeps))
推荐阅读
- android - 如何测试 Okhttp 的(单元和检测)
- java - Kotlin 使用 JDK 模块
- elasticsearch - Elasticsearch:文档数小于索引的文档数
- amazon-web-services - 如何从 Terraform 中的数据块输出值?
- r - 从列表的第 i 个条目中删除第一个 ki 元素
- asp.net-mvc - 从区域返回通用错误视图:如何使用控制器区域中的 _Layout 包装器?
- mysql - groupBy 期望在多对多关系中有更多的表列
- docker - docker-compose 环境与 docker -e 不一样
- javascript - Node.contains() 不包括分布式内容。什么是替代方案
- angular - 无法解析 'rxjs-compat/observable/combineLatest'