Clojure 如何将地图与其他集合进行比较来筛选地图

Clojure 如何将地图与其他集合进行比较来筛选地图,clojure,Clojure,我有一个包含这些{:ID2489,值:…..}{:ID5647,值:…..}的集合的映射,一直到10000,我想根据另一个集合过滤它的值,该集合的id是第一个,比如2489 我是clojure的新手,我尝试过: (into {} (filter #(some (fn [u] (= u (:id %))) [2489 3456 4567 5689]) record-sets)) 但是它只给了我最后一个5689 id作为输出{:id 5689,:values…},虽然我想要所有的,但是你能建议

我有一个包含这些{:ID2489,值:…..}{:ID5647,值:…..}的集合的映射,一直到10000,我想根据另一个集合过滤它的值,该集合的id是第一个,比如2489

我是clojure的新手,我尝试过:

(into {}  (filter #(some (fn [u] (= u (:id %))) [2489 3456 4567 5689]) record-sets)) 

但是它只给了我最后一个5689 id作为输出{:id 5689,:values…},虽然我想要所有的,但是你能建议我能做什么吗。

一个问题是,你从N个映射序列开始,然后你试着把它们塞进一个映射中。这将导致最后一个覆盖第一个


相反,您需要将输出设置为M个映射的序列M一个问题是,您从N个映射的序列开始,然后尝试将它们填充到单个映射中。这将导致最后一个覆盖第一个


相反,您需要让输出是一个M映射序列M另一种方法是使用Clojure中的函数

select keys仅返回给定给函数的键的映射

因此,假设您的数据是一个映射列表,我们可以使用将其转换为ID的哈希映射,然后对其调用select键

但是,现在这些值是ID的映射。所以为了得到原始结构,我们需要得到地图中的所有值,然后展平向量

; get all the values in the map
(vals (select-keys (group-by :id data) [1 4]))
; => ([{:id 1, :stuff :fred}] [{:id 4, :stuff :betty}])

; flatten the nested vectors
(flatten (vals (select-keys (group-by :id data) [1 4])))
; => ({:id 1, :stuff :fred} {:id 4, :stuff :betty})
提取值和展平可能看起来有点低效,但我认为它比需要在基于过滤器的方法中执行的嵌套循环要简单

可以使用threading宏将所有步骤组合在一起

(-> (group-by :id data)
    (select-keys [1 4])
    vals
    flatten)
您可以做的另一件事是从一开始就将数据存储为ID映射,这种方式使用选择键不需要分组,结果也不需要展平


这可能是解决此问题最有效的方法,但此结构可能不适用于所有情况

另一种方法是在Clojure中使用函数

select keys仅返回给定给函数的键的映射

因此,假设您的数据是一个映射列表,我们可以使用将其转换为ID的哈希映射,然后对其调用select键

但是,现在这些值是ID的映射。所以为了得到原始结构,我们需要得到地图中的所有值,然后展平向量

; get all the values in the map
(vals (select-keys (group-by :id data) [1 4]))
; => ([{:id 1, :stuff :fred}] [{:id 4, :stuff :betty}])

; flatten the nested vectors
(flatten (vals (select-keys (group-by :id data) [1 4])))
; => ({:id 1, :stuff :fred} {:id 4, :stuff :betty})
提取值和展平可能看起来有点低效,但我认为它比需要在基于过滤器的方法中执行的嵌套循环要简单

可以使用threading宏将所有步骤组合在一起

(-> (group-by :id data)
    (select-keys [1 4])
    vals
    flatten)
您可以做的另一件事是从一开始就将数据存储为ID映射,这种方式使用选择键不需要分组,结果也不需要展平


这可能是解决此问题最有效的方法,但此结构可能不适用于所有情况

您正在将所有地图压缩为一个。为了提高性能,第一件事是将ID列表更改为一个集合,然后简单地进行筛选

(let [ids (into #{} [2489 3456 4567 5689])]
  (filter (comp ids :id) record-sets))
这将为您提供正确的地图序列。如果要将此映射序列转换为ID键控的映射,可以执行以下操作:

(let [ids (into #{} [2489 3456 4567 5689])]
  (->> record-sets
       (filter (comp ids :id))
       (into {} (map (juxt :id identity)))))

您正在将所有地图压缩为一个。为了提高性能,第一件事是将ID列表更改为一个集合,然后简单地进行筛选

(let [ids (into #{} [2489 3456 4567 5689])]
  (filter (comp ids :id) record-sets))
这将为您提供正确的地图序列。如果要将此映射序列转换为ID键控的映射,可以执行以下操作:

(let [ids (into #{} [2489 3456 4567 5689])]
  (->> record-sets
       (filter (comp ids :id))
       (into {} (map (juxt :id identity)))))