【问题标题】:Clojure nested maps. Access parent-key from valueClojure 嵌套映射。从值访问父键
【发布时间】:2020-03-20 17:49:15
【问题描述】:

我是 Clojure 的新手。这个问题与this one 有关但不同。 假设我有嵌套地图:

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

假设我想在:something-that-uses-data 中访问(-> example :a :b :data)。如果有一些宏或关键字(如(-> this :data)),我是否必须以完全相同的方式调用它?几个小时都找不到相关的东西。

【问题讨论】:

  • 不确定我是否理解这个问题。您可能想使用get-in 而不是线程宏。
  • 地图内容未链接到地图。因此,如果您是?,您将无法知道自己在地图中。您必须跟踪根 + 路径,将其向下传递,然后从那里决定要做什么。
  • 我看到了一个入门解决方案。这就是我现在想要的。谢谢

标签: dictionary data-structures clojure nested


【解决方案1】:

我认为您正在尝试在 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)

【讨论】:

  • 谢谢。我只是想确保默认情况下它是“不可能的”。
【解决方案2】:

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

您可以通过 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] ...) }

【讨论】:

  • (get-in) 需要再次写下哈希映射中给定键的所有路径。我想知道哈希映射的元素是否“知道”它是具有一些默认函数或宏的父级。
  • 哈希图中的元素知道它的父元素。不可变数据结构的魔力可以廉价地修改(实际上)不允许循环。但是,访问者当然可以在访问孩子时记住父母。这是你从 zippers 中得到的东西之一(参见 clojure.zip)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-28
  • 2019-12-06
  • 1970-01-01
相关资源
最近更新 更多