2015-12-24 10 views
6

私はClojureには新しく、データ構造で基本的な操作を慣用的に実装するのは難しいです。Clojureでベクトルに対してダブルループを実装するための慣用方法は何ですか?

Clojureで次のコードを実装するための慣習的な方法はありますか?

l = [...] 
for i in range(len(l)): 
    for j in range(i + 1, len(l)): 
    print l[i], l[j] 
+0

すでに述べたように、 'doseq'は方法です。しかし、データを操作したいときは、おそらく 'map'または' for'があなたが探しているものです。 – user5187212

答えて

4

(最も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 

とバインドさコレクションが空である、または単一の要素を持っている場合、xsnil次のようになります。

user> (let [[x & xs] [1]] 
     (println x xs)) 
1 nil 
nil 

この機能を利用するには、:whileガードをリスト内包に使用してください。 map vectoriterateの使用についてどのようにxs

+1

'(v i)'を '(n番目のv i)'( 'v'がベクトルでないとき)に置き換えるべきです。 – user5187212

2

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 
関連する問題