2010/12/3 Ken Wesson <kwess...@gmail.com> > On Fri, Dec 3, 2010 at 10:08 AM, Laurent PETIT <laurent.pe...@gmail.com> > wrote: > > 2010/12/3 Laurent PETIT <laurent.pe...@gmail.com> > >> 2010/12/3 Anclj <anb...@gmail.com> > >>> I've got: > >>> > >>> user> (split (slurp "data") #",") > >>> ["0" "2" "1" "5" "2" "8" "3" "15" "4" "9"] > >>> > >>> And I would like: > >>> {:0 2, :1 5, :2 8, :3 15, :4 9} > >>> > >>> Any idea? > >> > >> > >> (let [s (split (slurp "data") #",")] > >> (zipmap (take-nth 2 s) (take-nth 2 (rest s)))) > > > > Sorry, this respects the contract better: > > > > (let [s ["1" "2" "3" "4" "5" "6"]] > > (zipmap > > (map keyword (take-nth 2 s)) > > (map #(Integer/valueOf %) (take-nth 2 (rest s))))) > > Both of these traverse s twice. How about: > > (let [s (split (slurp "data") #",")] > (into {} > (map (fn [[k v]] [(keyword (str k)) v]) > (partition 2 s)))) >
Indeed, if I analyze my solution: the 2 take-nth traverse s 2 times (creating 2 x 1/2 x n ISeq instances), and the two maps over the 2 resulting seq traverse these resulting seqs also, creating again 2 x 1/2 x n ISeq instances). In the end, 2 x 1/2 x n + 2 x 1/2 x n = 2 x n ISeq instances are created and visited. Now yours :-) : (partition 2 s) traverses s once, and creates 1/2 n ISeq instances each made of a seq of 2 ISeq instances => 1/2 n x 2 = n ISeq instances. Then map is applied and creates 1/2 x n vectors in 1/2 x n ISeq instances => also n instances created. In the end, your solution also creates 2 x n instances (ISeq instances and vector instances), before being consumed by into. In fact, when one knows the algorithm needs to consume the entire seq *by definition* (since in clojure datastructures themselves are not lazy, only seqs are), it sometimes feels odd to create all these intermediate objects. But I generally resist the temptation to too quickly resort to using loop, which is the real solution to not create too many intermediate objects: (let [s ["1" "2" "3" "4" "5" "6" "7" "8"]] (loop [s (seq s) m {}] (if s (recur (nnext s) (assoc m (keyword (first s)) (Integer/valueOf (fnext s)))) m))) or else by leveraging transients: (let [s ["1" "2" "3" "4" "5" "6" "7" "8"]] (loop [s (seq s) m (transient {})] (if s (recur (nnext s) (assoc! m (keyword (first s)) (Integer/valueOf (fnext s)))) (persistent! m)))) But really I generally not start (anymore) writing loops unless I see a performance problem! -- 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