When given the following set of vecs
#{[1 2 3] [9 8 3] [1 2] [1] [1 0 3 4] [1 2 3 4 5]}
find the closest match to [1 2 3]
(defn closest-match
"Searches the haystack vecs for the closest match to the needle vec"
[#^IPersistentVector needle #^IPersistentVector haystack]
(second
(last
(apply sorted-map
(apply concat
(map (fn [candidate]
[(reduce + (map #(if (= %1 %2) 1 0) needle candidate))
candidate])
haystack))))))
I wanted a three-step process:
1) Count the number of matching elements for each candidate
*2) When counts are equal, select the shortest candidate, discarding
the rest <-- help!
3) Return the candidate with the highest count
Stepping through the execution,
(map (fn [candidate]
[(reduce + (map #(if (= %1 %2) 1 0) needle candidate))
candidate])
haystack)
; returns ([1 [1]] [2 [1 0 3 4]] [3 [1 2 3]] [3 [1 2 3 4 5]]
[2 [1
2]] [1 [9 8 3]]), a vec matching counts to candidates
(apply concat ...
; returns (1 [1] 2 [1 0 3 4] 3 [1 2 3] 3 [1 2 3 4 5] 2 [1
2] 1 [9 8 3]) for consumption by "apply assoc {}" or "apply
sorted-map"
(apply sorted-map
; returns {1 [9 8 3], 2 [1 2], 3 [1 2 3 4 5]} <-- here is where
things get screwed up
When I apply the sorted-map, it will just take the last candidate for
matching counts. In other words, given (3 [1 2 3] 3 [1 2 3 4 5]) it
will return [1 2 3 4 5]. I'd instead like it to take the shorted
candidate, which in this case is [1 2 3].
What are some ways I could simplify/improve this function? How might I
implement my missing 2nd step so that it correctly picks the closest
match?
Rob
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en