Dictionary Clojure-过滤最内层的嵌套映射

Dictionary Clojure-过滤最内层的嵌套映射,dictionary,filter,clojure,Dictionary,Filter,Clojure,过滤以下嵌套映射并保持嵌套映射结构的最佳方法是什么。在我的示例中,Alice和Bob可以复制,例如,同一名员工可以同时在多个不同的工厂工作 (def universe {:customer1 {:plant1 { "Alice" {:age 35 :sex "F"} "Bob" {:age 25 :sex "M"}} :plant2 {}} :customer2 {} }) 例如,我想按年龄>30过滤并返回相同的地图结构。理想情况下

过滤以下嵌套映射并保持嵌套映射结构的最佳方法是什么。在我的示例中,Alice和Bob可以复制,例如,同一名员工可以同时在多个不同的工厂工作

(def universe
  {:customer1
    {:plant1
      { "Alice" {:age 35 :sex "F"}
        "Bob" {:age 25 :sex "M"}}
     :plant2 {}} 
   :customer2 {}
  })
例如,我想按年龄>30过滤并返回相同的地图结构。理想情况下,这将适用于任何嵌套贴图深度,在最内层进行过滤。预期结果:

(def universe
  {:customer1
    {:plant1
      { "Alice" {:age 35 :sex "F"}
        }
     :plant2 {}} 
   :customer2 {}
  })

我已经看过了,但它似乎没有解决我的问题。谢谢,

这与前面的一个问题非常相似:

(use '[com.rpl.specter])
(let [input          {:customer1
                                 {:plant1
                                          {"Alice" {:age 35 :sex "F"}
                                           "Bob"   {:age 25 :sex "M"}}
                                  :plant2 {}}
                      :customer2 {}}
      desired-output {:customer1
                                 {:plant1 {"Alice" {:age 35 :sex "F"}}
                                  :plant2 {}}
                      :customer2 {}}
      RECUR-MAP      (recursive-path [] p (cond-path map? (continue-then-stay [MAP-VALS p])))]

    (clojure.test/is (= (setval [RECUR-MAP (pred :age) #(> 30 (:age %))] NONE input)
                        desired-output)))

感谢@akond的回答,阅读代码让我想到了一个非幽灵解决方案。不过,有点惊讶的是,在这个用例中没有简单的方法来应用
过滤器

(defn recursive-filter [pred k m]
    (letfn [(pair-filter [pair] (if (pred (k (second pair))) pair nil))]
    (into {}
        (for [a m]
            (if (empty? (second a))
                [(first a) {}]
                (if (contains? (second a) k)
                    (pair-filter a)
                    [(first a) (recursive-filter pred k (second a))]))))))

您的数据有点不寻常,因为人们通常期望
:customer1
:customer2
等在向量中是不同的条目。对于这样的半结构化数据,我会考虑<代码> PASSWORK< <代码>:

(ns tst.demo.core
  (:use tupelo.core demo.core tupelo.test)
  (:require
    [clojure.walk :as walk] ))

(def universe
  {:customer1
    {:plant1
      {"Alice" {:age 35 :sex "F"}
       "Bob"   {:age 25 :sex "M"}}
      :plant2 {}}
   :customer2 {}})

(def age-of-wisdom 30)

(defn wisdom-only
  [form]
  (let [filter-entry? (when (map-entry? form)
                        (let [[-name- details]   form
                              age                (:age details)] ; => nil if missing
                          (and age ; ensure not nil
                            (< age age-of-wisdom))))]
    (if filter-entry?
      {}
      form)))

(walk/postwalk wisdom-only universe) => 
  {:customer1 
    {:plant1 
      {"Alice" {:age 35, :sex "F"}}
     :plant2 {}}
   :customer2 {}}
(ns tst.demo.core
(:使用tupelo.core demo.core tupelo.test)
(:需要
[clojure.walk:as walk]))
(定义宇宙)
{:客户1
{:工厂1
{“爱丽丝”{:35岁:性别“F”}
“鲍勃”{:25岁:性别“M”}
:plant2{}
:customer2{})
(智慧时代30)
(只有智慧
[表格]
(让[筛选条目](何时(地图条目?表格)
(让[[-姓名-详细信息]表格
年龄(:年龄详细信息);=>如果缺少,则为零
(b)年龄;确保不为零
(智慧时代)
(如果是筛选条目?
{}
表格))
(行走/行走后智慧专属宇宙)=>
{:客户1
{:工厂1
{“爱丽丝”{:35岁,性别“F”}
:plant2{}
:customer2{}

如果您还显示了所需的输出,那就太好了。