2011-08-13 14 views
16

Nie znalazłem wiele dokumentacji lub przykładów kodu do wykonywania manipulacji na wektorach map. Na przykład, jeśli mamWektor przetwarzania map w Clojure

(def student-grades 
[{:name "Billy" :test1 74 :test2 93 :test3 89} 
    {:name "Miguel" :test1 57 :test2 79 :test3 85} 
    {:name "Sandy" :test1 86 :test2 97 :test3 99} 
    {:name "Dhruv" :test1 84 :test2 89 :test3 94}]) 

i chcę dodać lub powiązać nową parę wartości klucza dla średnich test, który funkcjonuje powinienem przeczytać na? Także, jeśli ktoś wie o jakimkolwiek źródle/referencji dla wektorów map w Clojure, proszę udostępnij! Dzięki wielkie!

Odpowiedz

10

W tym przypadku chcesz map funkcja nad kolekcją (która akurat jest wektor); dla każdego elementu w kolekcji (który jest mapą - niefortunne zderzenie nazw), chcesz wygenerować nową mapę, która ma wszystkie pary klucz-wartość starej mapy, oraz nowy klucz, powiedzmy : średnia.

np.

(into [] ; optional -- places the answer into another vector 
    (map ; apply the given function to every element in the collection 
    (fn [sg] ; the function takes a student-grade 
     (assoc sg ; and with this student-grade, creates a new mapping 
     :avg ; with an added key called :avg 
     (/ (+ (:test1 sg) (:test2 sg) (:test3 sg)) 3.0))) 
    student-grades ; and the function is applied to your student-grades vector 
)) 

ps można użyć (doc fn-name), aby uzyskać dokumentację na nim; jeśli jesteś nowicjuszem w Clojure, radziłbym spotykać się z przyjaznymi ludźmi na irc.freenode.net #clojure i czytać książkę - moim ulubionym jest obecnie Programming Clojure, ale czekam na nadchodzącą książkę O'Reilly's Clojure z zapłatą oddech.

+0

Dziękuję bardzo! Właśnie przeglądałem clojuredocs.org i nie mogłem znaleźć odpowiednich przykładów dla kolekcji kolekcji. – Adam

+1

Bez problemu! Wydaje mi się, że nie jest to problemem, gdy już się do tego przyzwyczaisz - piękno programowania funkcjonalnego polega na tym, że bloki konstrukcyjne po prostu układają się w stosy, więc w przypadku zewnętrznej kolekcji można po prostu traktować wewnętrzne kolekcje, abstrakcyjnie, jako zwykłe elementy i podobnie, pisząc funkcję przekształcenia jednego z tych elementów, nie musisz się martwić zewnętrzną kolekcją. Dostaniesz powiesić to :) –

+2

Możesz również użyć '(mapv ...)' dla wygody dla '(na [] (mapa ...))'. – Peeja

4

Capra zapewnia już dobrą odpowiedź, ale tutaj jest kolejna realizacja dla porównania:

(defn average [nums] 
    (double (/ (apply + nums) (count nums)))) 

(map 
    #(assoc % :avg (average ((juxt :test1 :test2 :test3) %))) 
    student-grades) 

=> ({:avg 85.33333333333333, :name "Billy", :test1 74, :test2 93, :test3 89} etc....) 

Komentarze do uwaga:

  • Zazwyczaj warto oddzielenie ogólne funkcje, takie jak „średnie” w osobna, dobrze nazwana funkcja
  • juxt jest dość użyteczną funkcją w ogóle do wyodrębnienia określonej listy wartości składników z mapy
+0

Dzięki, uczę się wielu użytecznych funkcji, dodam do nich tę listę! – Adam

+0

Bez obaw! p.s. w tym przypadku użycie znaku jest nieco sprytne, ponieważ wykorzystuje ono fakt, że możesz używać słów kluczowych (": test1" itp.) jako funkcji. Ale możesz go używać z dowolnymi funkcjami. – mikera

+0

[Paradoks wynalazcy] (https://en.wikipedia.org/wiki/Inventor%27s_paradox): Czasami rozwiązanie ogólnego problemu może być łatwiejsze niż rozwiązanie konkretnego problemu. – Zaz

Powiązane problemy