简体   繁体   English

在Clojure中访问列表内的地图

[英]Accessing a map inside a list in Clojure

Here's the code : 这是代码:

(def entry {:name tempName :num tempNum})

(def tempList '(entry))

(println (get (nth tempList 0) (:name)))

Exception in thread "main" java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :name

In this bit of code, I define a map called entry containing a :name and a :num, then I put it in a list, then I try to print the :name field of the first (and only) element of the list. 在这段代码中,我定义了一个名为entry的映射,其中包含:name和:num,然后将其放入列表中,然后尝试打印列表中第一个(也是唯一一个)元素的:name字段。 (or at least this is what I think my code does :o) (或者至少这是我认为我的代码可以做到的:o)

I can access name from the entry map before I put it in the list, but once it's in the list I get this error. 在将名称放入列表之前,我可以从条目映射访问名称,但是一旦将其放入列表中,就会出现此错误。 What args am I supposed to give ? 我应该给什么参数?

There are two problems. 有两个问题。

First, for lists that contain symbols to be resolved (like the symbol entry in your case), you have to use syntax-quote (backtick) instead of regular quote (apostrophe); 首先,对于包含要解析符号的列表(例如您的案例中的符号条目),您必须使用语法引号 (反引号)而不是常规引号(撇号); so this line: 所以这行:

(def tempList '(entry))

should be: 应该:

(def tempList `(entry))

or just (using a vector, which is more idiomatic and easier to use in Clojure): 或只是(使用向量,它在Clojure中更惯用且更易于使用):

(def tempList [entry]) ; no quoting needed for vectors

Then, change this line 然后,更改此行

(println (get (nth tempList 0) (:name)))

to either this: 为此:

(println (get (nth tempList 0) :name))

or this: 或这个:

(println (:name (nth tempList 0)))

Using nth on a list is a bad idea because it has to do a linear search to retrieve your element, every time. 在列表上使用nth是个坏主意,因为它每次都必须进行线性搜索来检索元素。 Vectors are the right collection type to use here. 向量是在此处使用的正确集合类型。

Vectors are "maps" of indices to values. 向量是索引到值的“映射”。 If you use a vector instead of a list you can do this: 如果使用向量而不是列表,则可以执行以下操作:

(:name (tempList 0))

Or: 要么:

(get (get tempList 0) :name)

Or: 要么:

(get-in tempList [0 :name]))

take the ( ) off from (:name) on the 3rd line. 从第三行的(:name)取下()。 :keywords are functions that take a map as an argument and "look themselves up" which is quite handy though it makes the error slightly more confusing in this case :keywords是将地图作为参数并“查找自己”的函数,虽然在这种情况下会使错误稍微混乱,但它非常方便

(get (nth '({:name "asdf"}) 0) :name))

I would write your code like this: 我会这样写你的代码:

(def entry {:name tempName :num tempNum})

(def tempList (list entry))

(println (:name (first tempList)))

Note that first is much neater than using nth , and keywords can act as functions to look themselves up in the map. 请注意, first比使用nth更整洁,关键字可以充当在地图中查找自己的函数。 Another equivalent approach is to compose the functions and apply them to the list: 另一种等效的方法是组合功能并将其应用于列表:

((comp println :name first) tempList)

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

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