On Tuesday, January 10, 2017 at 1:59:05 PM UTC-5, Francis Avila wrote:
>
>
>
> On Tuesday, January 10, 2017 at 9:27:24 AM UTC-6, hiskennyness wrote:
>>
>> Whenever I code something like this I get the feeling a clojure guru 
>> could do it more simply, and I love learning new tricks.
>>
>> Here is my simple (real-world, btw) problem and solution. Is there a 
>> better way?
>>
>> ;; Problem: given optimized* json maps (* to avoid duplicating keys):
>> (def optij {:name [:tom :dick :harry]
>>            :age [1 2 3]
>>            :tone [:do :re :mi]})
>>
>> ;; ... produce normal repetitious maps
>> (comment
>>   [{:name :tom, :age 1, :tone :do}
>>    {:name :dick, :age 2, :tone :re}
>>    {:name :harry, :age 3, :tone :mi}])
>>
>> ;; goal #1: pivot so I can use zipmap
>> (comment
>>   ((:tom 1 :do) (:dick 2 :re) (:harry 3 :mi)))
>>
>> ;; my goal #1 approach (improvements welcome):
>> (apply (partial map (fn [& vs] vs))
>>        (vals optij))
>>
>> (apply (partial map vector)
>>        (vals optij))
>>
>>
>
> Your partials are not strictly necessary, apply "auto-partials" all but 
> the last argument:
>
> (apply map vector (vals optij))
>
>
Awesome. I tried applying map and it failed I guess because of something 
else so I gave up on it too soon.
 

>  
>  
>
>> ;; my overall approach (improvements welcome):
>> (let [ks (keys optij)
>>       vs-pivoted (apply (partial map vector)
>>                         (vals optij))]
>>   (vec (for [attributes vs-pivoted]
>>          (zipmap ks attributes))))
>>
>>
>
> This is a minor variation that uses transducers:
> (let [ks (keys optij)
>       vs-pivoted (apply map vector (vals optij))]
>   (into [] (map #(zipmap ks %)) vs-pivoted)) 
>

Nice. I fall back onto for-loops too quickly.
 

>
>
> This is a slightly different approach that combines keys and values first, 
> then pivots:
>
> (->> optij
>      (map (fn [[attr vs]] (mapv #(do [attr %]) vs)))
>      ;; [[[:name :tom][:name :dick]...], [[:age 1]...]]
>      (apply mapv (fn [& cols]
>                    ;; cols ([:name :tom] [:age 1] [:tone :do])
>                    (into {} cols))))
>
> This is a non-lazy approach that builds up the rows in multiple passes 
> without intermediate pivots or seqs:
>
> (reduce-kv (fn [rows k cols]
>              (reduce-kv
>                (fn [rows i col]
>                  (assoc-in rows [i k] col))
>                rows cols)) 
>   []
>   optij)
>
>
Sweet. I did actually code originally something that plucked values by 
column but decided to try the pivot approach because my plucking was not as 
terse as that.

Thx!

-kt

-- 
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.

Reply via email to