次のリストに最大演算子を適用する必要があります
[Tier20 Tier10 Tier30]
そして、それは私を与える必要があります
Tier30
定義済みの順序付きリスト (低いものから高いものへ) は次のとおりです。
[Tier5 Tier10 Tier20 Tier30 Tier40 Tier50]
Clojureでこれを達成する最良の方法は何ですか?
次のリストに最大演算子を適用する必要があります
[Tier20 Tier10 Tier30]
そして、それは私を与える必要があります
Tier30
定義済みの順序付きリスト (低いものから高いものへ) は次のとおりです。
[Tier5 Tier10 Tier20 Tier30 Tier40 Tier50]
Clojureでこれを達成する最良の方法は何ですか?
最初に順序を定義します。
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}
必要なのが最大値/最小値だけである場合は、オーダー マップを使用して入力を減らします。
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)
このマップを何度も変更する必要があり、毎回再ソートする必要がない場合は、データ構造を使用しsorted-set-by
て入力を保存します。
reduceを使用します。たとえば、リストLの最大値を見つけるには、次のようにします。
(reduce max L)
ここでの本当の問題は、投稿から完全に明確ではないため、層が文字列であるか、より複雑なオブジェクトであるかということです。どちらの方法でも、maxをラムダ式に置き換えて、次のように文字列の数値部分を引き出すことができます。
(reduce (fn [x y] ...) L)
ここで...は、データから数値部分を抽出する式になります。
これが私が試したところです。レバレッジの主なポイントは、のインスタンスメソッド.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からその順序付けインデックスへのハッシュマップによってはるかに優れたサービスが提供されます。
配列がの場合、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
ます。