繁体   English   中英

如何遍历复杂的 map 并根据 Clojure 中的模式删除密钥?

[英]How do I walk a complex map and remove keys based on a schema in Clojure?

我对 Clojure 还很陌生,如果这是一个愚蠢的问题,我很抱歉,但我有一个相当复杂的 map(它包含嵌套地图、向量等)。 在我将它放入我的数据库之前,我基本上想解开一堆我不需要保存写入速度的东西(在这种情况下,这是一个显着的性能改进)。 我想通过制作某种模式来过滤掉我不需要的所有位,这种模式可用于删除任何不必要的东西。 这是我试图实现的那种事情的一个例子(奇怪的例子,道歉:):

(def my-book
  {:intro {:one-liners [{:line "wowza" :rating 7} 
                        {:line "cool!" :rating 4}]}
           :how-many-lines 10
           :rubbish-one-liners [{:line "bongo" :rating 1}
                                {:line "foo"   :rating 2}]
            :other-info {:author {:name "me" :age 24}}})

(def my-schema
  [{:intro [{:one-liners {:values [:line :rating]}}
            {:values [:how-many-lines]}
            {:rubbish-one-liners {:values [:line]}}
            {:other-info {:author {:values [:name]}}}]}])

;;expected output when filtering via the schema:
(def my-output
  {:intro {:one-liners [{:line "wowza" :rating 7} 
                        {:line "cool!" :rating 4}]}
           :how-many-lines 10
           :rubbish-one-liners [{:line "bongo"}
                                {:line "foo"}]
            :other-info {:author {:name "me"}}})

我不确定该架构是否是 go 关于它/结构的最佳方式,一旦我有一个架构,如何实际 go 考虑到它似乎涉及很多不同的数据结构 - 所以我猜我的问题是,你会如何建议我 go 关于遍历我拥有的任何结构并根据模式删除键? :) 谢谢!

Clojure 有选择键,你只需要对嵌套结构使用递归。 尝试这样的事情:

(defn key-filter [obj schema]
  (cond 
    (vector? obj) (map #(select-keys % schema) obj)
    (map? obj) 
    (let [nw (select-keys obj (keys schema))
          res (map key-filter (vals nw) (vals schema))]
  (zipmap (keys nw) res))
    :else obj))

(def my-book {:intro {:one-liners [{:line "wowza", :rating 7} {:line "cool!", :rating 4}],
         :how-many-lines 10,
         :rubbish-one-liners [{:line "bongo", :rating 1} {:line "foo", :rating 2}],
         :other-info {:author {:name "me", :age 24}}}})

(def my-schema {:intro {:one-liners [:line], 
                        :how-many-lines [],
                        :rubbish-one-liners [:line], 
                        :other-info {:author {:name []}}}})

(key-filter my-book my-schema)

没有全面的库可以接受架构并通过删除额外的键等来强制数据结构与架构匹配。此外,您的架构和书籍结构之间存在一些不一致之处,例如哪些字段是向量或不是向量。

首先,我会使用 Spectre 库并手动编写所需的转换。 一个例子:

(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:require
    [com.rpl.specter :as sp]))

(dotest
  (let [book     {:intro              {:one-liners [{:line "wowza" :rating 7}
                                                    {:line "cool!" :rating 4}]}
                  :how-many-lines     10
                  :rubbish-one-liners [{:line "bongo" :rating 1}
                                       {:line "foo" :rating 2}]
                  :other-info         {:author {:name "me" :age 24}}}
        expected {:intro              {:one-liners [{:line "wowza" :rating 7}
                                                    {:line "cool!" :rating 4}]}
                  :how-many-lines     10
                  :rubbish-one-liners [{:line "bongo"}
                                       {:line "foo"}]
                  :other-info         {:author {:name "me"}}}]
    (is= expected
      (it-> book
        (sp/setval [:rubbish-one-liners sp/ALL :rating] sp/NONE it)
        (sp/setval [:other-info :author :age] sp/NONE it)))))

可以在此处查看此代码的实时示例。

请注意,Spectre 定义了一种 DSL,它本质上是一种单独的编程语言。 Spectre 非常强大,但需要一些练习和反复试验才能正确学习(类似于学习正则表达式语法)。

您还可以使用Tupelo Forest 库来完成此任务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM