3

我需要将 max 运算符应用于以下列表

[Tier20 Tier10 Tier30]

它应该给我

Tier30

预定义的有序列表(从低到高)是

[Tier5 Tier10 Tier20 Tier30 Tier40 Tier50]

在 Clojure 中实现这一目标的最佳方法是什么?

4

4 回答 4

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结构来存储您的输入。

于 2012-12-05T21:59:52.453 回答
2

使用减少。例如,要找到列表 L 的最大值,您可以:

(reduce max L)

这里真正的问题是您的层是字符串还是更复杂的对象,因为从您的帖子中并不完全清楚。无论哪种方式,您都可以用 lambda 表达式替换 max 以提取字符串的数字部分,如下所示:

(reduce (fn [x y] ...) L)

其中 ... 将是从数据中提取数字部分的表达式。

于 2012-12-05T20:06:04.960 回答
1

这是我刚刚尝试过的。杠杆的要点是实例方法.indexOfclojure.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 到其排序索引的哈希映射会为您提供更好的服务。

于 2012-12-05T20:08:18.173 回答
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.

于 2012-12-05T20:31:47.623 回答