4

adjacentsシーケンスの隣接ペアのベクトルを返す関数を作成しようとしています。そう(adjacents [1 2 3])返し[[1 2] [2 3]]ます。

(defn adjacents [s]
  (loop [[a b :as remaining] s
          acc []]
    (if (empty? b)
      acc
      (recur (rest remaining) (conj acc (vector a b))))))

私の現在の実装は文字列のシーケンスに対して機能しますが、整数または文字を使用すると、REPL は次のエラーを出力します。

IllegalArgumentException Don't know how to create ISeq from: java.lang.Long  clojure.lang.RT.seqFrom (RT.java:494)
4

2 に答える 2

5

ここでの問題は、 の最初の評価ループにあり(adjacents [1 2 3])aは にバインドされ1、にバインドさb2ます。次に、 かどうかを尋ねbますempty?。しかしempty?、シーケンスで機能し、シーケンスでbはありません。Longつまり、2です。この場合に使用できる述語は次のnil?とおりです。

user=> (defn adjacents [s]
  #_=>   (loop [[a b :as remaining] s acc []]
  #_=>     (if (nil? b)
  #_=>       acc
  #_=>       (recur (rest remaining) (conj acc (vector a b))))))
#'user/adjacents
user=> (adjacents [1 2 3 4 5])
[[1 2] [2 3] [3 4] [4 5]]

nilしかし、@amaloy が指摘しているように、データに正当な sがある場合、これは望ましい結果をもたらさない可能性があります。

user=> (adjacents [1 2 nil 4 5])
[[1 2]]

リストを使用した推奨される実装については、彼のコメントを参照してください。

Clojurepartitionを使用して、独自に定義する危険なしにこの作業を実行できることに注意してください。

user=> (partition 2 1 [1 2 3 4 5])
((1 2) (2 3) (3 4) (4 5))
user=> (partition 2 1 [1 2 nil 4 5])
((1 2) (2 nil) (nil 4) (4 5))
于 2013-01-21T23:25:32.190 に答える
3

これが私の短い答えです。すべてがベクトルになりますが、すべてのシーケンスで機能します。

(defn adjacent-pairs [s] 
  {:pre [(sequential? s)]}
  (map vector (butlast s) (rest s)))

テスト:

user=> (defn adjacent-pairs [s] (map vector (butlast s) (rest s))) 
#'user/adjacent-pairs
user=> (adjacent-pairs '(1 2 3 4 5 6))
([1 2] [2 3] [3 4] [4 5] [5 6])
user=> (adjacent-pairs [1 2 3 4 5 6])
([1 2] [2 3] [3 4] [4 5] [5 6])
user=> 

ただし、この回答はおそらく上記の回答よりも効率的ではありませpartitionん。

于 2013-09-01T22:49:58.867 に答える