Re: alter a map in a vector (reference)

2013-06-12 Thread Kelker Ryan
Here's the refactored version.user (def example
 (ref 
  [{:id 1 :email {"a...@mail.com" 1}}
   {:id 2 :email {"d...@mail.com" 1}}
   {:id 3 :email {"g...@mail.com" 2}}
   {:id 4 :email {"f...@mail.com" 2}}]))
#'user/example
user 
(defn update-counter [id xs]
  (dosync
   (let [_ @xs
 at-after (drop-while #(not= id (:id %)) _)
 mod-key (- at-after first :email keys first)
 location (- (count _) (count at-after))]
 (alter xs update-in [location :email mod-key] inc
#'user/update-counter
user (dotimes [_ 3]
	 (update-counter 3 example))
nil
user (clojure.pprint/pprint @example)
[{:email {"a...@mail.com" 1}, :id 1}
 {:email {"d...@mail.com" 1}, :id 2}
 {:email {"g...@mail.com" 5}, :id 3}
 {:email {"f...@mail.com" 2}, :id 4}]
nil
   12.06.2013, 14:47, "Meikel Brandmeyer (kotarak)" m...@kotka.de:Hi,Am Mittwoch, 12. Juni 2013 06:39:59 UTC+2 schrieb Kelker Ryan:user (defn update-counter [id xs](let [at-after (drop-while #(not= id (:id %)) @xs)
  to-modify (- at-after first :email)
  mod-key (- to-modify keys first)
  location (let [_ (- (count @xs) (count at-after))]
 (if-not (pos? _) 0 _))]
  (dosync
   (alter xs update-in [location :email mod-key] inc
 You have to wrap all accesses to xs in the same dosync. Kind regardsMeikel 



-- 
-- 
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: alter a map in a vector (reference)

2013-06-12 Thread Laurent PETIT
Hello,

A note about the code organization : I think you should strive to
separate the code that does side effects from the code that works on
the datastructures.

This means you could refactor your refactored version as such:

= (def example
 (ref
   [{:id 1 :email {a...@mail.com 1}}
{:id 2 :email {d...@mail.com 1}}
{:id 3 :email {g...@mail.com 2}}
{:id 4 :email {f...@mail.com 2}}]))

   (defn update-counter-val [v id]
 (let [at-after (drop-while #(not= id (:id %)) v)
   mod-key (- at-after first :email keys first)
   location (- (count v) (count at-after))]
   (update-in v [location :email mod-key] inc)))

   (defn update-counter [id xs]
 (dosync (alter xs update-counter-val id)))

   (dotimes [_ 3]
 (update-counter 3 example))

   @example
#'user/example
#'user/update-counter-val
#'user/update-counter
nil
[{:email {a...@mail.com 1}, :id 1} {:email {d...@mail.com 1}, :id
2} {:email {g...@mail.com 5}, :id 3} {:email {f...@mail.com 2},
:id 4}]


Finally, you could save you some pain if you had a representation of
the data that is more amenable to manipulation.
Depending on your requirements:
- do you really need a vector, or can you go with a set ?

e.g. change example to

(def example
  (ref
#{{:id 1 :email {a...@mail.com 1}}
  {:id 2 :email {d...@mail.com 1}}
  {:id 3 :email {g...@mail.com 2}}
  {:id 4 :email {f...@mail.com 2}}}))

This way, you can simplify the manipulation by using clojure.set :

= (require '[clojure.set :as s])

   (def example
 (ref
   #{{:id 1 :email {a...@mail.com 1}}
 {:id 2 :email {d...@mail.com 1}}
 {:id 3 :email {g...@mail.com 2}}
 {:id 4 :email {f...@mail.com 2}}}))

   (defn update-counter-val [v id]
 (let [r (first (s/select #(= id (:id %)) v))
   mod-key (- r :email keys first)]
   (- v (disj r) (conj (update-in r [:email mod-key] inc)

   (defn update-counter [id xs]
 (dosync (alter xs update-counter-val id)))

   (dotimes [_ 3]
 (update-counter 3 example))

   @example
nil
#'user/example
#'user/update-counter-val
#'user/update-counter
nil
#{{:email {a...@mail.com 1}, :id 1} {:email {f...@mail.com 2}, :id
4} {:email {g...@mail.com 5}, :id 3} {:email {d...@mail.com 1},
:id 2}}


Or alternatively, you can have the records indexed in a hashmap:

= (require '[clojure.set :as s])

   (def example
 (ref
   {1 {:id 1 :email {a...@mail.com 1}}
2 {:id 2 :email {d...@mail.com 1}}
3 {:id 3 :email {g...@mail.com 2}}
4 {:id 4 :email {f...@mail.com 2}}}))

   (defn update-counter-val [v id]
 (let [mod-key (- id v :email keys first)]
   (update-in v [id :email mod-key] inc)))

   (defn update-counter [id xs]
 (dosync (alter xs update-counter-val id)))

   (dotimes [_ 3]
 (update-counter 3 example))

   @example
nil
#'user/example
#'user/update-counter-val
#'user/update-counter
nil
{1 {:email {a...@mail.com 1}, :id 1}, 2 {:email {d...@mail.com 1},
:id 2}, 3 {:email {g...@mail.com 5}, :id 3}, 4 {:email
{f...@mail.com 2}, :id 4}}


Also, restructuring the record a little bit could help, but I don't
understand what it's about, so I don't know what to suggest.
Anyway, you could get rid of computing mod-key by leveraging some more
core clojure functions:

(require '[clojure.set :as s])

(def example
  (ref
{1 {:id 1 :email {a...@mail.com 1}}
 2 {:id 2 :email {d...@mail.com 1}}
 3 {:id 3 :email {g...@mail.com 2}}
 4 {:id 4 :email {f...@mail.com 2}}}))

(defn update-counter-val [v id]
  (letfn [(inc-email [m k v] (assoc m k (inc v)))]
(update-in v [id :email] #(reduce-kv inc-email {} %

(defn update-counter [id xs]
  (dosync (alter xs update-counter-val id)))

(dotimes [_ 3]
  (update-counter 3 example))

@example

(note : this example is a little bit more general: it increments each
value of each email found in the map under the :email key)

finally, if there is only one email per record, then maybe the
structure of the record should be simplified (and the resulting code)
as such:

= (require '[clojure.set :as s])

   (def example
 (ref
   {1 {:id 1 :email a...@mail.com :email-occurences 1}
2 {:id 2 :email d...@mail.com :email-occurences 1}
3 {:id 3 :email g...@mail.com :email-occurences 2}
4 {:id 4 :email f...@mail.com :email-occurences 2}}))

   (defn update-counter-val [v id]
 (update-in v [id :email-occurences] inc))

   (defn update-counter [id xs]
 (dosync (alter xs update-counter-val id)))

   (dotimes [_ 3]
 (update-counter 3 example))

   @example
nil
#'user/example
#'user/update-counter-val
#'user/update-counter
nil
{1 {:email-occurences 1, :email a...@mail.com, :id 1}, 2
{:email-occurences 1, :email d...@mail.com, :id 2}, 3
{:email-occurences 5, :email g...@mail.com, :id 3}, 4
{:email-occurences 2, :email f...@mail.com, :id 4}}

At this point, it becomes arguable, again, if update-counter-val
should exist on its own. Inlining it 

Re: alter a map in a vector (reference)

2013-06-11 Thread Yoshinori Kohyama
Solutions seem to depend on whether you have two or more mail addresses in 
a ':emails' section or not.
If you have, you should identify the mail address of which you want to 
increment the value.
Anyway, try below:

(dosync
  (alter result
(fn [v]
  (mapv second
(update-in (into {} (map #(vector (:id %) %) v))
  [1 :emails a...@mail.com]
  inc)

HTH,
with regards,
Yoshinori Kohyama

-- 
-- 
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: alter a map in a vector (reference)

2013-06-11 Thread Kelker Ryan
I've seen some interesting responses, but here's my solution. user (def example
(ref 
 [{:id 1 :email {"a...@mail.com" 1}}
  {:id 2 :email {"d...@mail.com" 1}}
  {:id 3 :email {"g...@mail.com" 2}}
  {:id 4 :email {"f...@mail.com" 2}}]))

#'user/example
user (defn update-counter [id xs]
(let [at-after (drop-while #(not= id (:id %)) @xs)
  to-modify (- at-after first :email)
  mod-key (- to-modify keys first)
  location (let [_ (- (count @xs) (count at-after))]
 (if-not (pos? _) 0 _))]
  (dosync
   (alter xs update-in [location :email mod-key] inc

#'user/update-counter
user (update-counter 4 example)
-- output removed --
user (update-counter 1 example)
-- output removed --
user (clojure.pprint/pprint @example)
[{:email {"a...@mail.com" 2}, :id 1}
 {:email {"d...@mail.com" 1}, :id 2}
 {:email {"g...@mail.com" 2}, :id 3}
 {:email {"f...@mail.com" 3}, :id 4}]
nil

   12.06.2013, 11:19, "Yoshinori Kohyama" yykohy...@gmail.com:   Solutions seem to depend on whether you have two or more mail addresses in a ':emails' section or not.  If you have, you should identify the mail address of which you want to increment the value.  Anyway, try below:  (dosync    (alter result      (fn [v]        (mapv second          (update-in (into {} (map #(vector (:id %) %) v))            [1 :emails "a...@mail.com"]            inc)  HTH,  with regards,  Yoshinori Kohyama  --  --  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: alter a map in a vector (reference)

2013-06-11 Thread Meikel Brandmeyer (kotarak)
Hi,

Am Mittwoch, 12. Juni 2013 06:39:59 UTC+2 schrieb Kelker Ryan:

 user (defn update-counter [id xs]

 (let [at-after (drop-while #(not= id (:id %)) @xs)
   to-modify (- at-after first :email)
   mod-key (- to-modify keys first)
   location (let [_ (- (count @xs) (count at-after))]
  (if-not (pos? _) 0 _))]
   (dosync
(alter xs update-in [location :email mod-key] inc


You have to wrap all accesses to xs in the same dosync.

Kind regards
Meikel
 

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




alter a map in a vector (reference)

2013-06-03 Thread Yinka Erinle
Hi,

I struggling to find a way to alter a value in a map that resides in a 
vector.

Given I have the following 
(def result (ref [ { :id 1 :emails { yi...@mail.com 1}} ] ) )

I like to alter the result in a transaction to become
[{:id 1 :emails { yi...@mail.com 2}}]; increment the counter from 1 
to 2

Please can someone provide pointers.

Thanks,
Yinka.

-- 
-- 
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: alter a map in a vector (reference)

2013-06-03 Thread Meikel Brandmeyer (kotarak)
Hi,

Am Montag, 3. Juni 2013 22:16:54 UTC+2 schrieb Yinka Erinle:

 Given I have the following 
 (def result (ref [ { :id 1 :emails { yi...@mail.com javascript: 1}} ] 
 ) )

 I like to alter the result in a transaction to become
 [{:id 1 :emails { yi...@mail.com javascript: 2}}]; increment the 
 counter from 1 to 2

 Please can someone provide pointers.


You can use the uniform update principle to stitch together alter and 
update-in.

(dosync
  (alter result update-in [0 :emails a@b.c] inc))

Kind regards
Meikel
 

-- 
-- 
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: alter a map in a vector (reference)

2013-06-03 Thread Yinka Erinle
Thanks Meikel for the prompt reply, that does it.

Please can you elaborate on how I can use the solution below to update a 
particular entry in the vector.

[{:id 1 :email {a...@mail.com 1}}
  {:id 2 :email {d...@mail.com 1}}
  {:id 3 :email {g...@mail.com 2}}]

So I will like to write a function that accepts an id and then updates the 
counter in email section of the given id.

(defn update-counter [x xs]  
   (dosync 
  (alter result ..

Thanks again for your time.

On Monday, June 3, 2013 9:23:47 PM UTC+1, Meikel Brandmeyer (kotarak) wrote:

 Hi,

 Am Montag, 3. Juni 2013 22:16:54 UTC+2 schrieb Yinka Erinle:

 Given I have the following 
 (def result (ref [ { :id 1 :emails { yi...@mail.com 1}} ] ) )

 I like to alter the result in a transaction to become
 [{:id 1 :emails { yi...@mail.com 2}}]; increment the counter from 
 1 to 2

 Please can someone provide pointers.


 You can use the uniform update principle to stitch together alter and 
 update-in.

 (dosync
   (alter result update-in [0 :emails a@b.c] inc))

 Kind regards
 Meikel
  


-- 
-- 
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: alter a map in a vector (reference)

2013-06-03 Thread Alex Baranosky
You *can* update this inside the vector, but if you want to key by :id, I
would personally recommend, you put the email data into a map and look it
up by :id, like this:

{1 {:id 1 :email {a...@mail.com 1}}
  2 {:id 2 :email {d...@mail.com 1}}
  3 {:id 3 :email {g...@mail.com 2}}}

Best,
Alex

On Mon, Jun 3, 2013 at 1:44 PM, Yinka Erinle yeri...@gmail.com wrote:

 Thanks Meikel for the prompt reply, that does it.

 Please can you elaborate on how I can use the solution below to update a
 particular entry in the vector.

 [{:id 1 :email {a...@mail.com 1}}
   {:id 2 :email {d...@mail.com 1}}
   {:id 3 :email {g...@mail.com 2}}]

 So I will like to write a function that accepts an id and then updates the
 counter in email section of the given id.

 (defn update-counter [x xs]
(dosync
   (alter result ..

 Thanks again for your time.


 On Monday, June 3, 2013 9:23:47 PM UTC+1, Meikel Brandmeyer (kotarak)
 wrote:

 Hi,

 Am Montag, 3. Juni 2013 22:16:54 UTC+2 schrieb Yinka Erinle:

 Given I have the following
 (def result (ref [ { :id 1 :emails { yi...@mail.com 1}} ] ) )

 I like to alter the result in a transaction to become
 [{:id 1 :emails { yi...@mail.com 2}}]; increment the counter from
 1 to 2

 Please can someone provide pointers.


 You can use the uniform update principle to stitch together alter and
 update-in.

 (dosync
   (alter result update-in [0 :emails a@b.c] inc))

 Kind regards
 Meikel


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