That makes sense. I updated the function to: (defn closest-match "Returns the closest matches of needle in the haystack" [#^IPersistentVector needle #^IPersistentVector haystack] (letfn [(matching [candidate] (println ">> checking " candidate) (reduce + (map #(if (= %1 %2) 1 0) needle candidate))) (closest [v1s v2] (cond (empty? v1s) [v2] (and (= (matching (first v1s)) (matching v2)) (= (count (first v1s)) (count v2))) (conj v1s v2) (or (> (matching (first v1s)) (matching v2)) (and (= (matching (first v1s)) (matching v2)) (< (count (first v1s)) (count v2)))) v1s :else [v2]))] (reduce #(closest %1 %2) [] haystack)))
This does work now: (closest-match [1 2 3] #{[1 2 \a] [1 2 \b] [2 1] [1] [1 2 \c] [1 2 3 4 5]}) [[1 2 3 4 5]] (closest-match [1 2] #{[1 2 \a] [1 2 \b] [2 1] [1] [1 2 \c] [1 2 3 4 5]}) [[1 2 \b] [1 2 \c] [1 2 \a]] (closest-match [2 1 3] #{[1 2 \a] [1 2 \b] [2 1] [1] [1 2 \c] [1 2 3 4 5]}) [[2 1]] One place I'm going to try to improve upon is how it reacts when there are no matches. Right now, it will return the smallest candidate because the third cond predicate will be true: (and (= (matching (first v1s)) (matching v2)) ; (= 0 0) (< (count (first v1s)) (count v2)))) v1s ; basically finds the smallest candidate (closest-match [\a \b] #{[1 2 \a] [1 2 \b] [2 1] [1] [1 2 \c] [1 2 3 4 5]}) [[1]] (closest-match [\a \b] #{[1 2 \a] [1 2 \b] [2 1] [1] [1 2 \c] [1 2 3 4 5] []}) [[]] I think when matches = 0, or there is literally no intersection between the needle and the candidates, I will just return []. Rob On Mon, Dec 28, 2009 at 6:28 PM, ajuc <aju...@gmail.com> wrote: > > > On 28 Gru, 20:57, Robert Campbell <rrc...@gmail.com> wrote: >> How might I add a third and final condition, where those candidates >> with equal scores AND equal counts are all returned together? > > Reduce can work with functions like > f : x * y -> x > > So we can modify function closest to be like that (untested): > > (closest [ v1s v2] > (if (empty v1s) > v2 > (cond > (and (= (matching (first v1s)) (matching v2)) > (= (count (first v1s)) (count v2))) (into > v1s v2)) > (or (> (matching (first v1s)) (matching v2)) > (and (= (matching (first v1s)) (matching v2)) > (< (count (first v1s)) (count v2)))) > [v1] > :else [v2]))) > > Also, we use matching on the same arguments a lot, so it would be good > to memoize that function. > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en