2017-01-25 5 views
0

Я пытался фильтровать комплексный вектор, как этотClojure- фильтр комплексный вектор

(def mySymbolT [[:name "salary" :type "string" :kind "static" :index 0] 
    [:name "money" :type "string" :kind "static" :index 1] 
    [:name "count" :type "int" :kind "field" :index 0]]) 

Моя цель состоит в том, чтобы вернуть количество элементов, которое имеет тот же вид: Например, для типа «статические» Я ожидайте 2 в качестве ответа. До сих пор я должен написать это:

(defn countKind [symbolTable kind] 
    (count(map first(filter #(= (:kind %) kind) symbolTable)))) 

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

ответ

4

Ваши данные будут лучше выражены как массив карты чем векторы:

(def your-table [{:name "salary", :type "string", :kind "static", :index 0} 
       {:name "money", :type "string", :kind "static", :index 1} 
       {:name "count", :type "int", :kind "field", :index 0}]) 

Вы можете попасть туда сюда ...

(def your-table 
    (mapv (partial apply array-map) mySymbolT)) 

Теперь мы можем

  • использовать ключевое слово :kind как функцию для извлечения этих значений и
  • основной функции frequencies, чтобы вернуть то, что вы спрашиваете.

Например ...

(frequencies (map :kind your-table)) 
;{"static" 2, "field" 1} 

Кстати, идиома Clojure является дефис слов в символе: my-symbol-t вместо mySymbolT.

+0

Я переключился на карты, хотя лучше знаю векторы. Из частот, например, как я могу фильтровать «статический» счет? Я пришел к '(второй (первый (фильтр # (= (первый%) вид) (частоты (map: kind symbol-table))))))', есть ли лучший способ? –

1

@ Миниатюра правильная, лучше изменить форму ваших данных. Но в случае, если это происходит из других источников, и вам просто нужно получить некоторые данные от него несколько раз (особенно, когда внутренние списки довольно короткие: теоретически это даже быстрее, чем конвертировать каждый из них для сопоставления и поиска ключа), вы можете избежать превращая его в вектор карты, как это:

первый вы можете сделать функцию, чтобы получить значение свойства по имени из вектора:

(defn plist-get [look-for items] 
    (when (seq items) 
    (if (= look-for (first items)) 
     (second items) 
     (recur look-for (drop 2 items))))) 

, а затем просто использовать его, чтобы получить результат:

user> (def data [[:name "salary" :type "string" :kind "static" :index 0] 
       [:name "money" :type "string" :kind "static" :index 1] 
       [:name "count" :type "int" :kind "field" :index 0]]) 
#'user/data 

user> (count (filter #(= "static" (plist-get :kind %)) data)) 
;;=> 2 
+1

Я думаю, что если вы собираетесь реализовать plist-get, вы также можете сделать это с разделом. '(второй (первый (фильтр # (= look-for (first%)) (разделы 2))))' – amalloy