我有以下结构
(def my-coll '{:data (
{:book/public-id #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c0", :book/name "AAA"}
{:book/public-id #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c1", :book/name "BBB"}
{:book/public-id #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c3", :book/name "CCC"}
)} )
我想只留下来自集合的id,例如用于过滤
(def filter-coll '(#uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c1" #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c2") )
我想要
{:data (
{:book/public-id #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c0", :book/name "AAA"}
{:book/public-id #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c3", :book/name "CCC"}
)}
我使用UUID以单一值过滤而没有问题:
(prn {:data (filter #(= (:book/public-id %) #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c0") (my-coll :data))})
其中 my-coll 是我的输入结构。 但是当我尝试按集合过滤时
(prn {:data (filter #(contains? (:book/public-id %) filter-coll) (my-coll :data))})
我收到了错误
contains? not supported on type: java.util.UUID
我可以通过集合UUID过滤输入结构的方式是什么?
答案 0 :(得分:2)
您必须切换contains?
的参数。这是一个稍微更惯用的版本:
(def my-coll '{:data
({:book/public-id #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c0"
:book/name "AAA"}
{:book/public-id #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c1"
:book/name "BBB"}
{:book/public-id #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c3"
:book/name "CCC"})})
;; Note I'm applying this into a set to have faster lookup.
(def filter-coll (set
'(#uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c1"
#uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c3")))
;; Here we use contains:
(filter #(contains? filter-coll (:book/public-id %)) (my-coll :data))
;; Here we use the fact that we can call 'sets' like functions:
(filter #(filter-coll (:book/public-id %)) (my-coll :data))
;; And an even shorter, and equivalent version with comp:
(filter (comp filter-coll :book/public-id) (:data my-coll))
答案 1 :(得分:1)
首先,对于contains?
个参数,集合应首先出现,而您正在寻找的项目应该排在第二位。但即使你交换参数,这也不会按预期工作,因为contains?
函数的行为是a bit different。
contains?
函数仅适用于键控集合,例如向量(其中键是元素索引),集合(其中键是集合中的项目)和映射。由于filter-coll
是列表,contains?
将抛出异常:
user> (contains? '(1 2 3) 1)
IllegalArgumentException contains? not supported on type: clojure.lang.PersistentList
尽管如此,您可以在filter-coll
中查找所需的值,如下所示:
{:data (filter #((set filter-coll) (:book/public-id %)) (my-coll :data))}
您甚至可以考虑将filter-coll
定义为set。因为filter-coll
的元素是uuids,所以set似乎很适合。
(def filter-coll #{#uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c1" #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c2"})
然后:
{:data (filter #(filter-coll (:book/public-id %)) (my-coll :data))}
答案 2 :(得分:1)
你几乎就在那里。首先,你得到了contains?
的参数顺序错误。所以收集首先是价值,然后是价值。
但是contains?
检查传递给它的集合(第一个参数)是否包含一个键,而不是一个等于你传递给contains?
的第二个参数的值,并且列表和向量这些键是索引:0,1,2 ......等等,所以在你的情况下没用。
你想要做的是将你的列表变成一个集合,这就是它。
(prn {:data (filter #(contains? (set filter-coll) (:book/public-id %)) (my-coll :data))})