3

私は今日4Clojureの問題に取り組んできましたが、問題 28で問題が発生し、flatten を実装しました。

私のコードには明確な問題がいくつかあります。

(fn [coll]
  ((fn flt [coll res]
    (if (empty? coll)
        res
        (if (seq? (first coll))
            (flt (into (first coll) (rest coll)) res)
            (flt (rest coll) (cons (first coll) res))))) coll (empty coll)))

いくつかの問題について考える方法について、いくつかの指針を使用できます。

  1. 結果のリストの順序を変更していないことを確認するにはどうすればよいですか? consどちらも、要素をconj追加するのが最も効率的な場所(リストの最初、ベクトルの最後など)に要素を追加するため、ジェネリックを操作するときにこれをどのように制御する必要があるのか​​ わかりません順序。

  2. 異なるタイプのネストされたシーケンスを処理するにはどうすればよいですか? たとえば、 will の入力は'(1 2 [3 4])will output([3 4] 2 1)を入力し、 will の入力は出力します。[1 2 '(3 4)](4 3 2 1)

  3. 私は「正しい」角度からこれに近づいていますか?これを行うには、アキュムレータで再帰的な内部関数を使用する必要がありますか、それとも明らかな何かが欠けていますか?

4

4 に答える 4

8

可能な限り HOF (高階関数) を使用するようにしてください。これにより、意図がより明確に伝わり、微妙な低レベルのバグが発生するのを防ぐことができます。

(defn flatten [coll]
  (if (sequential? coll)
    (mapcat flatten coll)
    (list coll)))
于 2013-04-23T08:56:29.123 に答える
1

1 つの可能なアプローチ:

(defn flatten [[f & r]]
  (if (nil? f)
    '()
    (if (sequential? f)
      (concat (flatten f) (flatten r))
      (cons f (flatten r)))))
于 2013-04-23T05:40:32.353 に答える
1

以下は、末尾呼び出しを最適化した方法で、1 回の反復内で、できる限り最小限の Clojure.core コードを使用して実行する方法です。

#(loop [s % o [] r % l 0]
   (cond
    (and (empty? s) (= 0 l))
    o
    (empty? s)
    (recur r
           o
           r
           (dec l))
    (sequential? (first s))
    (recur (first s)
           o
           (if (= 0 l)
             (rest s)
             r)
           (inc l))
    :else
    (recur (rest s)
           (conj o (first s))
           r
           l)))
于 2016-05-19T20:27:27.910 に答える