我是Clojure的初学者,我有一个简单的问题
假设我有一张由地图组成的列表。 每张地图都有:名称和:年龄
我的代码是:
(def Person {:nom rob :age 31 } )
(def Persontwo {:nom sam :age 80 } )
(def Persontthree {:nom jim :age 21 } )
(def mylist (list Person Persontwo Personthree))
现在我如何遍历列表。比方说,我有一个给定的名字。如何遍历列表以查看是否有任何Maps:name与my:name匹配。然后,如果有匹配的地图,我如何获得该地图的索引位置?
- 谢谢你
答案 0 :(得分:2)
(defn find-person-by-name [name people]
(let
[person (first (filter (fn [person] (= (get person :nom) name)) people))]
(print (get person :nom))
(print (get person :age))))
编辑:以上是问题的答案,因为它是在编辑问题之前;这里更新了一个 - filter
和map
开始变得混乱,所以我使用loop
从头开始重写:
; returns 0-based index of item with matching name, or nil if no such item found
(defn person-index-by-name [name people]
(loop [i 0 [p & rest] people]
(cond
(nil? p)
nil
(= (get p :nom) name)
i
:else
(recur (inc i) rest))))
答案 1 :(得分:2)
可以使用doseq:
完成此操作(defn print-person [name people]
(doseq [person people]
(when (= (:nom person) name)
(println name (:age person)))))
答案 2 :(得分:2)
我建议查看过滤功能。这将返回与某个谓词匹配的一系列项。只要您没有名称重复(并且您的算法似乎会指示这一点),它就会起作用。
答案 3 :(得分:1)
既然你改变了问题我会给你一个新的答案。 (我不想编辑我的旧答案,因为这会使评论非常混乱)。
可能有更好的方法来做到这一点......
(defn first-index-of [key val xs]
(loop [index 0
xs xs]
(when (seq xs)
(if (= (key (first xs)) val)
index
(recur (+ index 1)
(next xs))))))
此功能的用法如下:
> (first-index-of :nom 'sam mylist)
1
> (first-index-of :age 12 mylist)
nil
> (first-index-of :age 21 mylist)
2
答案 4 :(得分:0)
如何使用positions
中的clojure.contrib.seq
(Clojure 1.2)?
(use '[clojure.contrib.seq :only (positions)])
(positions #(= 'jim (:nom %)) mylist)
返回匹配索引的序列(如果要缩短列表,可以使用first
或take
。)
答案 5 :(得分:0)
(defn index-of-name [name people]
(first (keep-indexed (fn [i p]
(when (= (:name p) name)
i))
people)))
(index-of-name "mark" [{:name "rob"} {:name "mark"} {:name "ted"}])
1