7

私はこのような一連のマップペアを持っています (現在約 17000 ペア)

(def myseq '({:name "Peter" :rank 2222} {:name "Anna" :rank 111}))

特定のペアを新しいシーケンスにフィルタリングしたい

(filter (fn [x] (> x 222)) (:rank (first myseq)))

私はこのようにループを反復しようとしましたが、スレッドの死を続けています。また、単一のマップ コレクションでフィルターを使用すると、新しいシーケンスが返されるだけです。ここで自分で作成する必要があるかどうかわかりません。

(defn remove-lower [number myseq]
    (loop [i 0]
        (if (= i (count file))
            (println "done")
            (filter [x] (> x number))
                (:rank (first myseq))))
    (recur (rest myseq))))

最後に、ペアの新しいシーケンスを取得する最も効率的な方法はループですか?

4

2 に答える 2

8

ここではループ/再帰は必要ありません。filter はすでに seq を反復処理しています:

(filter (fn [entry] (> (:rank entry) 220)) myseq)
于 2012-07-24T08:14:33.460 に答える
6

最初に知っておくべきことは、(ほとんどの) clojure のデータ構造は不変であり、ほとんどの関数は機能的であるということです。つまり、副作用がないということです。あなたの場合filter、シーケンスはまったく変更されず、フィルタリングされていないアイテムのみを含む新しいシーケンスが返されます。

したがって、フィルタリングmyseqするには、次のようにする必要があります。

(def filtered-seq (filter (fn [x] ...) myseq))

Filter は関数を繰り返し呼び出し、xで現在フィルタリングされている項目にバインドしmyseqます。つまり、最初に にバインドされ{:name "Peter" :rank 2222}、次に にバインドされます{:name "Anna" :rank 111}。にはfiltered-seq、関数が true を返した要素のみが含まれます。myseq変更されません!

:rankしたがって、 222 より大きい要素のみを残す必要があります。

(filter (fn [x] (> (:rank x) 222)) myseq)

それでおしまい。filter についてもう 1 つ重要な点は、それが怠け者だということです。つまり、返されたコレクション内のアイテムは、必要な場合にのみ「実現」(または計算) されます。

仕事がうまくいくloopように、これを使用する必要はなく、怠惰ではありません。filterloop

とはいえ、いくつかの問題があるため、あなたloopは機能しません。

  1. recurの外loopです。この場合、clojure は関数の先頭にループ バックします。
  2. 戻り値を構築する必要があり、「現在の」要素を維持する必要があります
  3. 終了条件を適切に確認する必要があります

コードは次のようになります (未テスト)。

(defn remove-lower [number myseq]
  (loop [sq myseq res []]
     (if (empty? sq)
         res
         (let [current (first sq)]
           (if (> (:rank current) number)
              (recur (rest sq) (conj res current))
              (recur (rest sq) res))))))

方法に注意してください:

  1. recurの中にありますloop
  2. res戻り値をsq含み、現在残っているシーケンスを含みます
  3. それぞれが次の反復のためにとrecurの新しい値を渡しますsqres
  4. sqは反復ごとに「縮小」されるため、myseqが無限でない限り、ループは最終的に終了します。これをfilter、無限シーケンスを問題なく処理する と比較してください。

ご覧のとおり、これは読みにくく、一般的ではなくfilter、熱心です (怠惰ではありません)。

于 2012-07-24T08:19:54.513 に答える