Hi Mark, Here is a version runs about 1.3x faster on my setup.
(defn flatten-keys [thing] (letfn [(-map-key [prefix k] (str prefix "." (name k))) (-seq-key [prefix i] (str prefix "[" i "]")) (-flatten-entry [make-key prefix result entry] (let [[k v] entry] (-flatten-thing result (make-key prefix k) v))) (-flatten-thing [result key thing] (cond (map? thing) (reduce (partial -flatten-entry -map-key key) result (seq thing)) (sequential? thing) (reduce (partial -flatten-entry -seq-key key) result (map-indexed vector thing)) :else (assoc! result key thing)))] (persistent! (-flatten-thing (transient {}) (if (map? thing) "$" "") thing)))) And it can take an empty collection as argument. Sebastien Le mardi 17 février 2015 17:14:29 UTC+1, Mark Watson a écrit : > > I want to flatten a map of nested maps/vecs > > Currently I'm using the fn's: > > (defn- flatten-keys* [a ks m] > > (cond > > (map? m) (reduce into > > (map (fn [[k v]] > > (flatten-keys* a (if-not (empty? ks) > > (str ks "." (name k)) > > (str "$." (name k))) v)) (seq > m))) > > (and (sequential? m) > > (not (instance? clojure.lang.MapEntry m))) (reduce into > > (map-indexed (fn > [idx itm] > > > (flatten-keys* a > > > (str ks "[" idx "]") > > > itm)) > > (seq > m))) > > :else (assoc a ks m))) > > (defn flatten-keys [m] (flatten-keys* {} "" m)) > > (flatten-keys {:name {:first "Rich" :last "Hickey"} :number [1 415 123 4567]}) > > ;; => {"$.number[0]" 1, "$.number[1]" 415, "$.number[2]" 123, "$.number[3]" > 4567, "$.name.first" "Rich", "$.name.last" "Hickey"} > > > However, I was wondering if anyone had suggestions on a more performant fn? > > I have a white-list of possible flattened keys. But, the list is big > (~1200), and with with most (~95%) of the keys having corresponding vals = > nil it was much less performant using get-in on every possible key. > > Thanks for the help! > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.