Reputation: 7986
I'm trying to do exercise 20 on https://iloveponies.github.io/120-hour-epic-sax-marathon/recursion.html. Here's my code:
(defn my-frequencies-helper [freqs a-seq]
(let [first-elem (first a-seq)
rest-of-seq (rest a-seq)]
(if (nil? first-elem)
freqs
(if (contains? freqs first-elem)
(assoc freqs first-elem (inc (get freqs first-elem)))
(assoc freqs first-elem 1)))))
(defn my-frequencies [a-seq]
(my-frequencies-helper {} a-seq))
The problem is that this is not recursive. Somehow I need to add the following line into my-frequencies-helper
after updating the freqs
map:
(my-frequencies-helper freqs rest-of-seq)
Since it isn't dependent on a branch of an if
function, I can't see how to do it without adding too many parameters to the if
functions. I.e. it doesn't fit a cond
or if
because it's a step I want to call after doing another, functionally unrelated step.
I've probably got it wrong, but imperatively I just want to recursively call my-frequencies-helper
after updating the map, i.e. in python something like:
freqs[first-elem] = freqs[first-elem] + 1
my-frequencies-helper(freqs, rest-of-seq) # just another step to execute
How can I lever this into my code (or more likely, what would be another simple way to approach this)?
Upvotes: 2
Views: 206
Reputation: 20194
We can simplify this code quite a bit with the help of destructuring:
(defn my-frequencies-helper
[freqs [first-elem & rest-of-seq :as a-seq]]
(if (empty? a-seq)
freqs
(let [updated-freqs (if (contains? freqs first-elem)
(assoc freqs first-elem (inc (get freqs first-elem)))
(assoc freqs first-elem 1))]
(my-frequencies-helper updated-freqs rest-of-seq))))
Furthermore there is a common idiom for
(if (contains? freqs first-elem)
(assoc freqs first-elem (inc (get freqs first-elem)))
(assoc freqs first-elem 1))
The following is equivalent, as long as you would not store nil in the place of one of the numbers:
(update-in freqs [first-elem] (fnil inc 0))
This leaves us with the following simplified function:
(defn my-frequencies-helper
[freqs [first-elem & rest-of-seq :as a-seq]]
(if (empty? a-seq)
freqs
(my-frequencies-helper (update-in freqs [first-elem] (fnil inc 0)) rest-of-seq)))
Upvotes: 4
Reputation: 4748
For each item in the list, you'd want to look up in the result dictionary, to see if that item is already there, if so, you'd save it +1, if not, just store 1 in that dictionary.
with this you could solve it with a simple recursion, or use reduce.
Spoiler:
(defn my-frequencies [x] (reduce(fn[t n](assoc t n (inc(get t n 0)))) {} x))
Upvotes: 0