'Calculating image of a Set in Clojure includes nil value?
(defn image-of
"computes the image of the element x under R"
[R x]
(set
(for [r R]
(when (= (first r) x)
(second r)))))
Function idea: Add the second variable in R when it's first is equal to x.
So this function is supposed to compute image of a relation. This is kinda successful. When running a test I get this result:
Input: (image-of #{[1 :a] [2 :b] [1 :c] [3 :a]} 1)
Expected: #{:c :a}
Actual: #{nil :c :a}
So it includes a nil value for some reason. What in the function causes this? I guess I could filter out any nil values but would like to have the solution on a single line.
Solution 1:[1]
So the problem was I didn't know exactly how to use when
This solution does it:
(set (for [r R
:when (= (first r) x)]
(second r)))
Solution 2:[2]
Let me suggest a different approach.
The natural way to represent a relation in Clojure is as a map from keys to sets (or other collections) of values. A function to convert your collection of pairs to this form is ...
(defn pairs->map [pairs]
(reduce
(fn [acc [key value]]
(assoc acc key (conj (acc key #{}) value)))
{}
pairs))
For example, ...
(pairs->map #{[1 :a] [2 :b] [1 :c] [3 :a]})
=> {2 #{:b}, 1 #{:c :a}, 3 #{:a}}
You can use this map as a function. I you feed it a key, it returns the corresponding value:
({2 #{:b}, 1 #{:c :a}, 3 #{:a}} 1)
=> #{:c :a}
You construct this map once and or all and use it as often as you like. Looking it up as a function is effectively a constant-time operation. But you run through the entire collection of pairs every time you evaluate image-of.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Alan Thompson |
| Solution 2 | Thumbnail |
