私はClojureには新しく、データ構造で基本的な操作を慣用的に実装するのは難しいです。Clojureでベクトルに対してダブルループを実装するための慣用方法は何ですか?
Clojureで次のコードを実装するための慣習的な方法はありますか?
l = [...]
for i in range(len(l)):
for j in range(i + 1, len(l)):
print l[i], l[j]
私はClojureには新しく、データ構造で基本的な操作を慣用的に実装するのは難しいです。Clojureでベクトルに対してダブルループを実装するための慣用方法は何ですか?
Clojureで次のコードを実装するための慣習的な方法はありますか?
l = [...]
for i in range(len(l)):
for j in range(i + 1, len(l)):
print l[i], l[j]
(最もFP-っぽいではなく)最も簡単なのはあなたの例とほぼ同じです:
(let [v [1 2 3 4 5 6 7]]
(doseq [i (range (count v))
j (range (inc i) (count v))]
(println (v i) (v j))))
、ここでは、(それが基づいていないすべてのこれらのペアを生成するために、より機能的変異体であります長さまたは指数、むしろ尾反復で):
(let [v [1 2 3 4 5 6 7]]
(mapcat #(map (partial vector (first %)) (rest %))
(take-while not-empty (iterate rest v))))
出力:
([1 2] [1 3] [1 4] [1 5] [1 6] [1 7] [2 3] [2 4]
[2 5] [2 6] [2 7] [3 4] [3 5] [3 6] [3 7] [4 5]
[4 6] [4 7] [5 6] [5 7] [6 7])
は、ただの副作用のためにdoseq
でこれらのペアを使用します。
(let [v [1 2 3 4 5 6 7]
pairs (fn [items-seq]
(mapcat #(map (partial vector (first %)) (rest %))
(take-while not-empty (iterate rest items-seq))))]
(doseq [[i1 i2] (pairs v)] (println i1 i2)))
更新:@のdg123の答え以下。それはいいですが、あなたはそれをさらに良くすることができ、doseq
年代とfor
「非構造や警備員などのsの機能を使用して:
(let [v [1 2 3 4 5 6 7]]
(doseq [[x & xs] (iterate rest v)
:while xs
y xs]
(println "x:" x "y:" y)))
あなたがコレクションの尾を反復処理が、iterate
が無限に作り出すことを、覚えておいてくださいcoll:
user> (take 10 (iterate rest [1 2 3 4 5 6 7]))
([1 2 3 4 5 6 7] (2 3 4 5 6 7) (3 4 5 6 7)
(4 5 6 7) (5 6 7) (6 7) (7)()()())
なので、空のコレクションだけを含めるように制限する必要があります。 非構造フォーム[x & xs]
は、最初のパラメータと休息のparamsのシーケンスに引数を分割:
user> (let [[x & xs] [1 2 3 4 5 6]]
(println x xs))
1 (2 3 4 5 6)
nil
とバインドさコレクションが空である、または単一の要素を持っている場合、xs
はnil
次のようになります。
user> (let [[x & xs] [1]]
(println x xs))
1 nil
nil
この機能を利用するには、:while
ガードをリスト内包に使用してください。 map vector
とiterate
の使用についてどのようにxs
'(v i)'を '(n番目のv i)'( 'v'がベクトルでないとき)に置き換えるべきです。 – user5187212
でx
、すべての項目について
:怠惰を生成
user=> (def l [1 2 3 4 5])
#'user/l
user=> (map vector l (iterate rest (drop 1 l)))
([1 (2 3 4 5)] [2 (3 4 5)] [3 (4 5)] [4 (5)] [5()])
各i
インデックスの値のシーケンスとそれに続くj
のすべてが続きます。
あなたは、あなたがそうのようなfor
を使用して必要な値のペアのすべての反復処理することができます:あなたの代わりに怠惰なシーケンスを生成するのIOを実行したい場合
user=> (for [[i js] (map vector l (iterate rest (drop 1 l)))
j js]
[i j])
([1 2] [1 3] [1 4] [1 5] [2 3] [2 4] [2 5] [3 4] [3 5] [4 5])
使用doseq
を:
user=> (doseq [[i js] (map vector l (iterate rest (drop 1 l)))
j js]
(println (str "i: " i " j: " j)))
i: 1 j: 2
i: 1 j: 3
i: 1 j: 4
i: 1 j: 5
i: 2 j: 3
i: 2 j: 4
i: 2 j: 5
i: 3 j: 4
i: 3 j: 5
i: 4 j: 5
nil
すでに述べたように、 'doseq'は方法です。しかし、データを操作したいときは、おそらく 'map'または' for'があなたが探しているものです。 – user5187212