Re: Create map from vector of keywords and other items
Thank you all for your valuable input. I'll look into these soon. take-nthis definitely a function to keep in mind. Stefan -- -- 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/groups/opt_out.
Re: Create map from vector of keywords and other items
'keycollect-partition' looks sensible and idiomatic to me... perhaps juxt can come into play here? Of course, both versions will only work with keys as keywords and non-keys as non-keywords. If you use anything else other than a keyword for a key or a keyword for an item, both will break... Jim On 20/02/13 11:50, Stefan Kamphausen wrote: Hi, given a vector of the form [:key1 1 2 3 :key2 4 :key3 5 6 7] I wand to create a map collecting the items behind each keyword as a vector like this: {:key1 [1 2 3] :key2 [4] :key3 [5 6 7]} I have already written two functions which achieve this, but neither of them feels good and I am interested in more elegant and idiomatic solutions. (defn keycollect-partition [coll] (- coll (partition-by keyword?) ; bundle at key (partition 2); kw + its arg (map (fn [[[sec] arg]] [sec (vec arg)])) ; destruct the mess (into {}))) ; make it a map (defn keycollect-reduce [coll] (apply zipmap (reduce (fn [ac x] (if (keyword? x) [(conj (first ac) x) (conj (second ac) [])] (update-in ac [1 (dec (count (first ac)))] conj x))) [[] []] coll))) Added complexity: My original vector does not yet contain keywords, but I construct them in amap regexp-matching each item and creating a keyword from the first group of the match. Any pointers or ideas appreciated. Regards, Stefan -- -- 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/groups/opt_out. -- -- 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/groups/opt_out.
Re: Create map from vector of keywords and other items
Not sure if this is any more idiomatic, or feels any better, but I thought a loop would be appropriate here, plus I made key selection pluggable. https://gist.github.com/thheller/4995766 (defn split-into-map [items key-fn] see gist) key-fn is a function which accepts one arg and should return true if the arg is supposed to be a key. (prn (split-into-map [:key1 1 2 3 :key2 4 :key3 5 6 7] keyword?)) (prn (split-into-map [y 1 2 x 3 4 5] string?)) Requirement is that the first item is a key, since it would break otherwise. Cheers, /thomas On Wednesday, February 20, 2013 12:50:42 PM UTC+1, Stefan Kamphausen wrote: Hi, given a vector of the form [:key1 1 2 3 :key2 4 :key3 5 6 7] I wand to create a map collecting the items behind each keyword as a vector like this: {:key1 [1 2 3] :key2 [4] :key3 [5 6 7]} I have already written two functions which achieve this, but neither of them feels good and I am interested in more elegant and idiomatic solutions. (defn keycollect-partition [coll] (- coll (partition-by keyword?) ; bundle at key (partition 2); kw + its arg (map (fn [[[sec] arg]] [sec (vec arg)])) ; destruct the mess (into {}))) ; make it a map (defn keycollect-reduce [coll] (apply zipmap (reduce (fn [ac x] (if (keyword? x) [(conj (first ac) x) (conj (second ac) [])] (update-in ac [1 (dec (count (first ac)))] conj x))) [[] []] coll))) Added complexity: My original vector does not yet contain keywords, but I construct them in a map regexp-matching each item and creating a keyword from the first group of the match. Any pointers or ideas appreciated. Regards, Stefan -- -- 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/groups/opt_out.
Re: Create map from vector of keywords and other items
Don't know if it's better, but: (apply hash-map (map-indexed #(if (= 0 (mod %1 2)) (first %2) (vec %2)) (partition-by keyword? [:key1 1 2 3 :key2 4 :key3 5 6 7]))) Seems to work. Mauricio -- -- 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/groups/opt_out.
Re: Create map from vector of keywords and other items
And this is mine (defn keycollect-too [key-fn coll] (let [not-key (complement key-fn)] (loop [[k more] coll, res (transient {})] (let [[vv rr] (split-with not-key more)] (if-not k (persistent! res) (recur rr (assoc! res k (vec vv (keycollect-too keyword? [:key1 1 2 3 :key2 4 :key3 5 6 7]) = {:key1 [1 2 3], :key2 [4], :key3 [5 6 7]} Thanks. On Wednesday, February 20, 2013 6:50:42 AM UTC-5, Stefan Kamphausen wrote: Hi, given a vector of the form [:key1 1 2 3 :key2 4 :key3 5 6 7] I wand to create a map collecting the items behind each keyword as a vector like this: {:key1 [1 2 3] :key2 [4] :key3 [5 6 7]} I have already written two functions which achieve this, but neither of them feels good and I am interested in more elegant and idiomatic solutions. (defn keycollect-partition [coll] (- coll (partition-by keyword?) ; bundle at key (partition 2); kw + its arg (map (fn [[[sec] arg]] [sec (vec arg)])) ; destruct the mess (into {}))) ; make it a map (defn keycollect-reduce [coll] (apply zipmap (reduce (fn [ac x] (if (keyword? x) [(conj (first ac) x) (conj (second ac) [])] (update-in ac [1 (dec (count (first ac)))] conj x))) [[] []] coll))) Added complexity: My original vector does not yet contain keywords, but I construct them in a map regexp-matching each item and creating a keyword from the first group of the match. Any pointers or ideas appreciated. Regards, Stefan -- -- 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/groups/opt_out.
Re: Create map from vector of keywords and other items
whatever the implementation I would include some example in the doc, like: (defn keycollect-*fnnamehere** **input: [:key1 1 2 3 :key2 4 :key3 5 6 7] output: {:key1 [1 2 3] :key2 [4] :key3 [5 6 7]} * [coll] ;... implementation here ) wish clojure has this kind of doc(s) instead, or at least this if not + some words to explain On Wed, Feb 20, 2013 at 12:50 PM, Stefan Kamphausen ska2...@gmail.comwrote: Hi, given a vector of the form [:key1 1 2 3 :key2 4 :key3 5 6 7] I wand to create a map collecting the items behind each keyword as a vector like this: {:key1 [1 2 3] :key2 [4] :key3 [5 6 7]} I have already written two functions which achieve this, but neither of them feels good and I am interested in more elegant and idiomatic solutions. (defn keycollect-partition [coll] (- coll (partition-by keyword?) ; bundle at key (partition 2); kw + its arg (map (fn [[[sec] arg]] [sec (vec arg)])) ; destruct the mess (into {}))) ; make it a map (defn keycollect-reduce [coll] (apply zipmap (reduce (fn [ac x] (if (keyword? x) [(conj (first ac) x) (conj (second ac) [])] (update-in ac [1 (dec (count (first ac)))] conj x))) [[] []] coll))) Added complexity: My original vector does not yet contain keywords, but I construct them in a map regexp-matching each item and creating a keyword from the first group of the match. Any pointers or ideas appreciated. Regards, Stefan -- -- 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/groups/opt_out. -- Please correct me if I'm wrong or incomplete, even if you think I'll subconsciously hate it. -- -- 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/groups/opt_out.