使用 UUID 过滤其他集合的集合映射
Filter map of collection by other collection with UUID
我有以下结构
(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 过滤输入结构的方法是什么?
您必须切换 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))
首先,对于 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
定义为集合。因为,filter-coll
的元素是 uuid,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))}
你快到了。首先,您将 contains?
的参数顺序弄错了。所以集合先行,然后是价值。
但是 contains?
检查您传递给它的集合(第一个参数)是否包含一个键,而不是等于您传递给 contains?
的第二个参数的值,并且在列表和向量的情况下,这些键是索引:0、1、2 ...等等,所以这对您来说是无用的。
你想做的是将你的列表变成一个集合,然后就可以了。
(prn {:data (filter #(contains? (set filter-coll) (:book/public-id %)) (my-coll :data))})
我有以下结构
(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 过滤输入结构的方法是什么?
您必须切换 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))
首先,对于 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
定义为集合。因为,filter-coll
的元素是 uuid,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))}
你快到了。首先,您将 contains?
的参数顺序弄错了。所以集合先行,然后是价值。
但是 contains?
检查您传递给它的集合(第一个参数)是否包含一个键,而不是等于您传递给 contains?
的第二个参数的值,并且在列表和向量的情况下,这些键是索引:0、1、2 ...等等,所以这对您来说是无用的。
你想做的是将你的列表变成一个集合,然后就可以了。
(prn {:data (filter #(contains? (set filter-coll) (:book/public-id %)) (my-coll :data))})