Обход списка карт - PullRequest
3 голосов
/ 14 июля 2009

Я новичок в 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))

Теперь, как мне пройти по списку. Скажем, например, что у меня есть имя: имя. Как просмотреть список, чтобы узнать, соответствует ли какое-либо из Карт: имя моему: имя. И затем, если есть карта, которая соответствует, как я могу получить позицию индекса этой карты?

-Спасибо

Ответы [ 6 ]

2 голосов
/ 14 июля 2009

Я бы посоветовал взглянуть на функцию фильтра. Это вернет последовательность элементов, которые соответствуют некоторому предикату. До тех пор, пока у вас нет дублирования имен (и ваш алгоритм, похоже, диктует это), он будет работать.

2 голосов
/ 14 июля 2009

Это можно сделать с помощью дозыq :

(defn print-person [name people]
  (doseq [person people]
    (when (= (:nom person) name)
      (println name (:age person)))))
2 голосов
/ 14 июля 2009
(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 голос
/ 14 июля 2009

Поскольку вы изменили свой вопрос, я даю вам новый ответ. (Я не хочу редактировать свой старый ответ, так как это может привести к путанице в комментариях.)

Возможно, есть лучший способ сделать это ...

(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
0 голосов
/ 28 ноября 2011
(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
0 голосов
/ 28 ноября 2011

Как насчет использования positions из clojure.contrib.seq (Clojure 1.2)?

(use '[clojure.contrib.seq :only (positions)])
(positions #(= 'jim (:nom %)) mylist)

Возвращает последовательность совпадающих индексов (вы можете использовать first или take, если хотите сократить список).

...