nth does not collect from vector inside a loop

111 views Asked by At

I'm using re-frame, and I have a bind an atom to my-collection like this:

my-collection (atom {:one [] :two [] :three [] :four [] :five [] :six [] :seven [] :eight []})

Then I dispatch it to assoc to db and later, I will subscribe to it to use in a doseq like this:

(doseq [each (:one my-collection)]
    (if)

    (if)

    (if)
 )

Ther are now 8 doseq which I'm trying to put it on maybe a loop to avoid writing long doseq for 8 times. How can I do that?

I've tried this but it does not work:

(let [parts [:one :two :three :four :five :six :seven :eight]
      index (atom 0)]

    (loop [each ((nth parts @index) my-collection)]
        (do
            (if (= :one (nth parts @index)
            some code)

            (if (= :four (nth parts @index)
            some code)

            (if (= :eight (nth parts @index)
            some code)

            (swap! index inc)
            (recur (nth parts @index))
        )
     )
)

Update:

I also need to use the keywords from parts, inside each if.

3

There are 3 answers

4
erdos On

how about using nested doseq macros?

(doseq [part [:one :two :three :four]]
   (doseq [each (get my-collection part)]
      ; ...
   ))
0
leetwinski On

something like this should work.

(def my-collection 
 (atom {:one [:a :b] 
        :two [:c :d] 
        :three [:e :f] 
        :four [:g :h] 
        :five [:aa :bb] 
        :six [:cc :dd] 
        :seven [:ee :ff] 
        :eight [:gg :hh]}))

(doseq [k [:one :two :three :four :five :six :seven :eight]
        item (k @my-collection)]
  ;; replace this one with your business code
  (printf "processing item %s from part %s\n" item k))

;; processing item :b from part :one
;; processing item :c from part :two
;; processing item :d from part :two
;; processing item :e from part :three
;; processing item :f from part :three
;; processing item :g from part :four
;; processing item :h from part :four
;; processing item :aa from part :five
;; processing item :bb from part :five
;; processing item :cc from part :six
;; processing item :dd from part :six
;; processing item :ee from part :seven
;; processing item :ff from part :seven
;; processing item :gg from part :eight
;; processing item :hh from part :eight
0
amd.srinivas On

Can't really provide exact help without knowing the usecase inside your if blocks. But if iterating over each key-value pair and applying a specific code is your usecase, map would be perfect choice here.

With the following collection:

(def my-collection 
 (atom {:one [1] 
        :two [2] 
        :three [3] 
        :four [4] 
        :five [5] 
        :six [6] 
        :seven [7] 
        :eight [8]}))

You should define your logic as a function, say:

(defn process-kv [[key value]]
    ;; You would probably have a `cond` with specific condition for each key.
    {(name key) (apply list value)})

And map this function over your collection like so:

(map process-kv (seq @my-collection))

This would result in:

({one (1)} 
 {two (2)} 
 {three (3)} 
 {four (4)} 
 {five (5)} 
 {six (6)} 
 {seven (7)} 
 {eight (8)})

You can further ignore processing unknown keys in your collection by adding a keep to your map's output.