2017-09-21 23 views
7

Clojureの入門者として、最も簡単なことを表現するのが難しい場合がよくあります。たとえば、PythonでClojureでベクトルの最後の要素を置き換える方法

v[-1]=new_value 

なり、ベクトルの最後の要素を交換するために、私はClojureの中に、以下の亜種で終わる:

言ってかなり長く、無表情で
(assoc v (dec (count v)) new_value) 

最小、または

(conj (vec (butlast v)) new_value) 

実行時間がO(n)であるため、さらに悪化します。

それはクラブでスイスの時計を修復しようとしている洞窟人のように、私には馬鹿げた感じがします。

ベクトルの最後の要素を置き換える正しいClojureの方法は何ですか?だから、基本的に10時間、それは10倍遅い要素数の

(def v (vec (range 1e6))) 
#'user/v 
user=> (time (first (conj (vec (butlast v)) 55))) 
"Elapsed time: 232.686159 msecs" 
0 
(def v (vec (range 1e7))) 
#'user/v 
user=> (time (first (conj (vec (butlast v)) 55))) 
"Elapsed time: 2423.828127 msecs" 
0 


butlast -version(Clojureは1.8)のための私の O(n) -claimをサポートするために。

+1

あなたの最初の方法は、それがどのように行われるかです。明らかに、あなたはそれをきれいにするために "最後に置き換える"関数を書くことができます。私はそれを表現するPythonの過度の簡潔な方法は残念なことにあなたの期待を損なってしまったと思います。私はClojureで独自の構文を保証するために、しばしば後方からの索引付けが必要であるとは思わない。 +1が間違っていることを証明したいからです。 – Carcigenicate

+0

注: 'v'がすでにベクトルであれば、解#3はO(n)ではありません(測定が別の方法で証明されない限り、Clojureベクトルをデフォルト選択として常に使用することをお勧めします)。 –

+1

これはよく区切られた特定の質問と答えですが、私は、Pythonでインデックス式で表現された多くのアルゴリズムが、インデックスを使用する必要のない慣用的なClojureの同等物を持っていることを指摘する価値があると思います。 – glts

答えて

9

私は

(set-top [1 2 3] :a) 
=> [1 2 :a] 

、例えば

(defn set-top [coll x] 
    (conj (pop coll) x)) 

を使用したいしかし、それはまた、リストのフロント上で動作します:

(set-top '(1 2 3) :a) 
=> (:a 2 3) 

Clojureのスタック機能 - peekpop、およびconj - 順次コレクションの自然なオープンエンドで作業します。

しかし正しい方法はありません。


さまざまなソリューションが空のベクターにどのように反応しますか?あなたの(assoc v (dec (count v)) new_value)と私(defn set-top [coll x] (conj (pop coll) x))がするように

  • あなたのPython v[-1]=new_valueは、例外がスローされます。
  • (conj (vec (butlast v)) new_value)[new_value]を返します。 butlastは効果がありません。
1

「純粋」であることを主張すると、2番目または3番目の解決策が機能します。

(s/defn replace-at :- ts/List 
    "Replaces an element in a collection at the specified index." 
    [coll  :- ts/List 
    index :- s/Int 
    elem  :- s/Any] 
    ...) 

(is (= [9 1 2] (replace-at (range 3) 0 9))) 
(is (= [0 9 2] (replace-at (range 3) 1 9))) 
(is (= [0 1 9] (replace-at (range 3) 2 9))) 
As with drop-at, replace-at will throw an exception for invalid values of index. 

同様のヘルパー関数が

  • を追加

    • 挿入-で
    • 先頭に追加
    • ドロップでのために存在する:私は、ヘルパー関数from the Tupelo libraryを使用して単純&より明示的なことを好みます

    上記のすべてがClojureリスト(eagerまたはlazy)またはClojureベクトルのどちらかの場合にも同様に機能することに注意してください。あなたの例のように入力を最初にベクトルに強制的に強制するのではない限り、The conj solution will failを使用してください。

    +3

    と 'assoc'と比較してどのような利得ですか? – ead

    関連する問題