我需要将max运算符应用于以下列表
[Tier20 Tier10 Tier30]
它应该给我
Tier30
预定义的有序列表(从低到高)是
[Tier5 Tier10 Tier20 Tier30 Tier40 Tier50]
在Clojure中实现这一目标的最佳方法是什么?
答案 0 :(得分:6)
首先定义排序:
user> (def order '[Tier5 Tier10 Tier20 Tier30 Tier40 Tier50])
#'user/order
然后我们将订单映射到可以通过创建map
user> (def order-map (zipmap order (range)))
{Tier50 5, Tier40 4, Tier30 3, Tier20 2, Tier10 1, Tier5 0}
如果您需要的是最大/最小值,请使用order-map减少输入:
user> (reduce #(if (< (order-map %1) (order-map %2)) %1 %2)
'[Tier20 Tier10 Tier30])
Tier30
<小时/> 或者如果你需要完整的排序,那么使用sort-by函数,就像常规排序函数一样,除了它让你有机会在比较之前翻译输入:
user> (sort-by (zipmap order (range)) '[Tier20 Tier10 Tier30])
(Tier10 Tier20 Tier30)
如果您需要经常修改此地图而不是每次都重新排序,那么使用sorted-set-by
数据结构来存储您的输入。
答案 1 :(得分:2)
使用reduce。例如,要查找列表L的最大值,您可以执行以下操作:
(reduce max L)
这里真正的问题是你的Tiers是字符串还是更复杂的对象,因为你的帖子并不完全清楚。无论哪种方式,你可以用lambda表达式替换max来拉出字符串的数字部分,如下所示:
(reduce (fn [x y] ...) L)
where ...将是从数据中提取数字部分的表达式。
答案 2 :(得分:1)
这是我刚试过的。杠杆的主要观点是.indexOf
上的实例方法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>
当然,这是O(n 2 )。如果您将大规模地执行此操作,您可以通过从TierN到其排序索引的哈希映射更好地服务。
答案 3 :(得分:0)
如果数组是java.lang.String
,那么可以使用一些互操作:
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
如果不只是让他们实施Comparable
,或创建Comparator
。