2

UdacityのPythonベースのCS212を使用し、Clojureに変換するという私の旅を続けて、次のような関数を作成しようとしています。

  1. シーケンス内のすべてのアイテムを返します。
  2. シーケンスの最大値に等しい、
  3. ベクトルを返す「キー」関数を使用する

Clojureのmax-key関数は、整数を返すためにキーが必要なことを除いて、ほとんどこれを行います。この場合、整数を返す必要はありません。ベクトルを返します。いくつかの変更を加えると、compare関数を使用して、キーイング関数によって返されるベクトルを比較できます。

(defn all-max-key
  "Returns a vector of x for which (k x), arbitrated by compare, are greatest."
  ([k x] x)
  ([k x y] (if (= 1 (compare (k x) (k y))) x y))
  ([k x y & more]
     (reduce #(all-max-key k %1 %2) (all-max-key k x y) more)))

ここで、問題は、これが同点を考慮していないことです(compareは0を返します)。つまり、リスト内のすべての要素は一意ですが、キーイング関数ごとに同等の値を持つものもあります。命令型の世界では、リストをループして最大値を追跡し、各要素をそれに比較してから、変更可能なリストを追加/置換する場合があります。

しかし、ループに頼らずにこれを行うには、慣用的でエレガントで機能的な方法が必要だと思います。私がreduceを使用しようとすると、すべて、シーケンスとメンバー要素の無意味な比較が発生しました。誰かがこれに光を当てることができますか?

4

1 に答える 1

2

これにより、最大アイテムのベクトルが返されます。

(defn maximal-key [k x & xs]
  (reduce (fn [ys x]
            (let [c (compare (k x) (k (peek ys)))]
              (cond
                (pos? c) [x]
                (neg? c) ys
                :else    (conj ys x))))
          [x]
          xs))

REPLでのテスト:

;; convoluted key function to demonstrate that vector keys are fine
user> (maximal-key #(vector (first %))
                    (list 1 2 3) (list 4 5 6) (list 3 6 8)
                    (list 4 7 9) (list 1 5 9))
[(4 5 6) (4 7 9)]

compare最初の引数が2番目の引数よりも大きいことを示すために、任意の正の整数を返す場合があることに注意してください。したがって、pos?の代わりに== 1

于 2013-01-07T23:59:30.103 に答える