How can I control each element in a vector AND refer to a previous value in Clojure?

Given:

(def my-vec [{:a "foo" :b 10} {:a "bar" :b 13} {:a "baz" :b 7}]) 

How can I iterate over each element to print this element: a and the sum of everything: b to this point? I.e:

"foo" 10
bar 23
"baz" 30

I tried similar things to no avail:

 ; Does not work! (map #(prn (:a %2) %1) (iterate #(+ (:b %2) %1) 0)) my-vec) 

This does not work, because the β€œiteration” of lazy-seq cannot refer to the current element in my-vec (as far as I can tell).

TIA! Sean

+4
source share
3 answers
 user> (reduce (fn [total {:keys [ab]}] (let [total (+ total b)] (prn a total) total)) 0 my-vec) "foo" 10 "bar" 23 "baz" 30 30 
+6
source

You can look at this, starting with a sequence of cards, filtering out a sequence of values: a and a separate sequence of a moving sum of values: b, and then matching the function of two arguments to two derived sequences.

create a sequence of only values: a and: b with

 (map :a my-vec) (map :b my-vec) 

then the function to get the moving amount:

  (defn sums [sum seq] "produce a seq of the rolling sum" (if (empty? seq) sum (lazy-seq (cons sum (recur (+ sum (first seq)) (rest seq)))))) 

then connect them:

 (map #(prn %1 %s) (map :a my-vec) (sums 0 (map :b my-vec))) 

This separates the problem of generating data from its processing . Hope this makes life easier.

PS: the best way to get a moving amount?

+1
source

Convert it to a summarized sequence:

 (defn f [start mapvec] (if (empty? mapvec) '() (let [[ m & tail ] mapvec] (cons [(m :a)(+ start (m :b))] (f (+ start (m :b)) tail))))) 

Called as:

 (f 0 my-vec) 

returns:

 (["foo" 10] ["bar" 23] ["baz" 30]) 
0
source

Source: https://habr.com/ru/post/1302809/


All Articles