Reputation: 1502
I need to apply the max operator to the following list
[Tier20 Tier10 Tier30]
And it should give me
Tier30
The predefined ordered list (from low to high) is
[Tier5 Tier10 Tier20 Tier30 Tier40 Tier50]
What's the best way to achieve this in Clojure?
Upvotes: 3
Views: 380
Reputation: 91534
first define the ordering:
user> (def order '[Tier5 Tier10 Tier20 Tier30 Tier40 Tier50])
#'user/order
then we map the order onto something that can be sorted by creating a map
user> (def order-map (zipmap order (range)))
{Tier50 5, Tier40 4, Tier30 3, Tier20 2, Tier10 1, Tier5 0}
use the order-map to reduce the input if all you need is the max/min:
user> (reduce #(if (< (order-map %1) (order-map %2)) %1 %2)
'[Tier20 Tier10 Tier30])
Tier30
user> (sort-by (zipmap order (range)) '[Tier20 Tier10 Tier30])
(Tier10 Tier20 Tier30)
if you need to modify this map a lot and not re-sort it each time then use a sorted-set-by
datastructure to store your inputs.
Upvotes: 6
Reputation: 8432
If the array is of java.lang.String
then with a bit of interop:
user=> (def array ["Tier5" "Tier10" "Tier20" "Tier30" "Tier40" "Tier50"])
#'user/array
user=> (defn find-max [m] (reduce #(if (> (.compareTo %1 %2) -1) %1 %2) m))
#'user/find-max
user=> (find-max array)
"Tier50"
user=> (find-max "a")
\a
If not just make them implement Comparable
, or create a Comparator
.
Upvotes: 0
Reputation: 3830
Use reduce. For instance, to find the maximum of a list L, you would do:
(reduce max L)
The real question here is if your Tiers are strings or more complex objects, as it isn't completely clear from your post. Either way, you can replace max with a lambda expression to pull out the numeric part of the string, like so:
(reduce (fn [x y] ...) L)
Where ... will be the expression that extracts the numeric portion out of your data.
Upvotes: 2
Reputation: 200148
Here's what I've just tried. The main point of leverage is the instance method .indexOf
on clojure.lang.Vector
.
user> (def x ['Tier5 'Tier10 'Tier20 'Tier30 'Tier40 'Tier50])
#'user/x
user> (index-of x 'Tier10)
; Evaluation aborted.
user> (.indexOf x 'Tier10)
1
user> (def y ['Tier20 'Tier10 'Tier30])
#'user/y
user> (reduce #(max %1 (.indexOf x %2)) y)
; Evaluation aborted.
user> (x (reduce #(max %1 (.indexOf x %2)) 0 y))
Tier30
user>
Naturally, this is O(n2). If you'll do this on a large scale, you'll be much better served by a hash-map from TierN to its ordering index.
Upvotes: 1