2013-07-27 18 views
9

Biorąc pod uwagę zagnieżdżoną mapę z tylko kluczami słów kluczowych, taką jak {:foo {:bar 1 :baz [2 3] :qux {:quux 4}} :corge 5}, jak mogę zaimplementować flatten-map, aby (flatten-map {:foo {:bar 1 :baz [2 3] :qux {:quux 4}} :corge 5} "-") wyprodukował coś w rodzaju {:foo-bar 1 :foo-baz [2 3] :foo-qux-quux 4 :corge 5}.Spłaszczanie mapy przez dołączanie do kluczy

Moja najlepsza próba jest:

(defn flatten-map 
    ([form separator] (flatten-map form separator nil)) 
    ([form separator prefix] 
    (if (map? form) 
    (into {} (map (fn [[k v]] 
        [(keyword (str prefix (name k))) 
        (flatten-map v separator (str prefix (name k) separator))]) 
        form)) 
    form))) 

Jak widać nie mogę flatten-map aby wybrać tylko te „listki”.

Odpowiedz

11
(defn flatten-map 
    ([form separator] 
    (into {} (flatten-map form separator nil))) 
    ([form separator pre] 
    (mapcat (fn [[k v]] 
       (let [prefix (if pre (str pre separator (name k)) (name k))] 
       (if (map? v) 
        (flatten-map v separator prefix) 
        [[(keyword prefix) v]]))) 
       form))) 

zostałeś bezwarunkowo tworzenie nowych par klucz/wartość, nawet gdy wartość była zostać rozszerzona, więc przeszedłem mapę do mapcat tak, że wynik mógłby być „podciągnięte” do górnego poziomu (to także wymagany podział (into {} ...) do wersji najwyższego poziomu formularza, ponieważ w rzeczywistości nie chcemy żadnych map poza najwyższym poziomem danych wyjściowych).

Oto jak to działa z przykładu:

user> (flatten-map {:foo {:bar 1 :baz [2 3] :qux {:quux 4}} :corge 5} "-") 
{:foo-bar 1, :foo-qux-quux 4, :foo-baz [2 3], :corge 5} 
+0

Perfect! Dziękuję Ci. –