Clojure获取嵌套地图的值

21

我习惯在应用程序中使用嵌套数组或映射设置。我尝试像这样在Clojure中设置:

(def gridSettings
  {:width 50
   :height 50
   :ground {:variations 25}
   :water {:variations 25}
   })

我想知道你是否知道一个能够获取嵌套值的好方法?我尝试写了下面这行代码:

(:variations (:ground gridSettings))

这个方案是可行的,但它是反向的和相当繁琐的,特别是如果我增加几个级别。


1
mtaka和dbyrne的回答都是解决这个问题的常见方法。使用任何一种方法都可以!我想指出,get-in可以使您的意图更清晰。 - WolfeFan
2
我认为现在是时候接受其中一个答案了。我的内心选择 dbyrne ,但我的头脑选择 mtyaka :) - joelittlejohn
@joelittlejohn 很难选择一个答案,因为它们都是正确和有用的,我认为最好的服务是让人们阅读它们全部! - Joakim Tall
4个回答

38

这就是get-in的作用:

(get-in gridSettings [:ground :variations])

从文档字符串中得知:

clojure.core/get-in
([m ks] [m ks not-found])
  Returns the value in a nested associative structure,
  where ks is a sequence of keys. Returns nil if the key
  is not present, or the not-found value if supplied.

30

您可以使用thread-first宏:

(-> gridSettings :ground :variations)

在两个特殊情况下,我更喜欢使用->而不是get-in:

  • 键是在运行时确定的任意序列。
  • 当提供未找到值时有用。

如果 (:ground gridSettings) 是空的,结果会是什么? - arajek
2
整个表达式的结果将只是 nil。不会抛出任何异常。 - dbyrne
(:ground nil) ;=> nil 使用->似乎也是Clojure惯用语法。 - danneu
4
但是, -> 运算符可以与 or 一起使用,以便更好地返回未找到的值。(get-in grid-settings [:ground :variations] "not found!")(-> grid-settings :ground :variations (or "not found!")) 相比。 - danneu
当您需要谓词而不是关键字时,即在查找导航路径上的下一步需要调用函数时,您也可以使用->。 - user100464

14

除了其他答案提到的 (get-in-> 宏),有时候您想从一个地图(嵌套或不嵌套)中获取多个值,在这种情况下,解构可以非常有帮助。

除了其他答案提到的 (get-in-> 宏),有时候您想从一个地图(嵌套或不嵌套)中获取多个值,在这种情况下,解构可以非常有帮助。

(let [{{gv :variations} :ground
       {wv :variations} :water} gridSettings]
  [gv wv]) 

3

地图是部分函数(不是完全函数)。因此,我们可以将它们简单地应用为函数。基于所给地图:

(gridSettings :ground)
;=> {:variations 25}

结果是一个映射。因此,它可以再次应用,这将导致与问题中提出的类似(但不是反向的)“语法”。
((gridSettings :ground) :variations)
;=>25 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接