2016-05-18 107 views
0

我有以下結構過濾圖的其他集合與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"} 
    )}) 

,我想通過

(def filter-coll '(#uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c1" #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c2")) 

我想離開只是從集合ID進入,例如用於過濾獲得通過UUID這種方式單一值

{: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"} 
    )} 

我過濾沒有問題:

(prn {:data (filter #(= (:book/public-id %) #uuid "555b6f35-4e8c-42c5-bb80-b4d9147394c0") (my-coll :data))}) 

其中我 - 科爾是我的輸入結構。 但當我嘗試通過過濾收集

(prn {:data (filter #(contains? (:book/public-id %) filter-coll) (my-coll :data))}) 

我有錯誤

contains? not supported on type: java.util.UUID 

什麼辦法,我可以通過收集UUID過濾輸入結構?

回答

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

首先,對於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的元素是uuids,所以在這裏似乎很適合。

(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))} 
1

你幾乎沒有。首先你得到了錯誤的參數順序contains?。所以收藏首先是價值。

contains?檢查您傳遞給它的集合(第一個參數)是否包含一個鍵,而不是等於您傳遞給contains?的第二個參數的值,對於列表和向量,這些鍵是索引:0,1,2 ...等等,這對你的情況沒用。

你想做什麼,而是把你的列表變成一個集合,那就做到了。

(prn {:data (filter #(contains? (set filter-coll) (:book/public-id %)) (my-coll :data))})