Clojure嵌套地图。从值访问父键

时间:2020-03-20 17:49:15

标签: dictionary data-structures clojure nested

我是Clojure的新手。该问题与this one有关,但有所不同。 说我嵌套了地图:

(def example
  {:a {:b 2 :data [1 2 3] :something-that-uses-data ?}})

假设我要访问(-> example :a :b :data)中的:something-that-uses-data。是否必须使用与某些宏或关键字(例如(-> this :data)之类的关键字)完全相同的方法来调用它?几个小时找不到任何相关内容。

2 个答案:

答案 0 :(得分:0)

我认为您正在尝试模仿Clojure中的对象。对象具有将数据和处理该数据的功能打包在一起的类,但是在像Clojure这样的功能语言中,数据和功能是分开的。

因此,Clojure中的惯用方式是函数方法,它只是对不可变数据起作用的函数。 Clojure中唯一的OO功能是协议,用于多态。

我认为您在示例中想要的是:


(def example
  {:a {:b 2 :data [1 2 3]}})

(defn something-that-uses-data [{{:keys [data] :a}}]
  (do-work-with data))

您当然可以有一个包含数据和函数的映射,但是仅当函数不同并且您想在顺序上下文中应用这些函数时,该映射才有用。像这样...但是我只是在猜测您的上下文可能是什么。

  (map (fn [[k v]
         (let [data (:data v)
               f (:somthing-that-uses-data v)]
           (f data)))
       collection-of-maps)

答案 1 :(得分:0)

我不确定我是否理解这个问题。您可以编辑以阐明所需的行为吗?

您可以通过3种方式访问​​Tupelo库中的深层数据结构。

  • 使用tupelo.forest处理树状数据结构。 See the docs,并确保观看视频。

  • 您可以使用tupelo.core/destruct,这是使用模板的get-in的较高级版本。参见the examples here

  • 您可以对数据结构进行深度优先遍历,并使用walk-with-parents跟踪每个节点的父级。参见the examplesthe docs


访问嵌套数据元素的父级

您可以使用walk-with-parentswalk-with-parents-readonly进行此操作。考虑以下简单的嵌套数据结构:

(def data {:a 1 :b {:c 3}} )

我们可以遍历数据结构,记住从根到每个元素的路径。当我们到达元素3时,我们具有以下父数据路径:

(walk-with-parents data <noop-intc>) =>

:parents => [ {:a 1, :b {:c 3}}   ; the orig map
              [:b {:c 3}]         ; the MapEntry for key :b
              {:c 3}              ; the map where value 3 
              [:c 3] ]            ; the MapEntry with value 3
:data => 3

因此拦截器将通过2个参数调用:

  • 4个元素的父母路径向量
  • 数据项本身

对于-readonly变体,侦听器功能可以进行验证并在检测到问题时引发异常。对于非只读变量,返回值将替换数据元素。每个拦截器都是一个2元素映射,如下所示:

{:enter (fn [parents data] ...)
 :leave (fn [parents data] ...) }