2017-07-02 18 views
2

私の最初の試みだった:ベクターから要素を削除し

境界エラーで終わる
I = Vector{String}(["first", "second", "third", "fourth"]) 

for i in I 
    if i == "fourth" 
     splice!(I, 4) 
    end 
    print("$i\n") 
end 

:私はちょっと「手書き」道からそれを考え出し

その後
BoundsError(String["first", "second", "third"], (5,)) 

I = Vector{String}(["first", "second", "third", "fourth"]) 

state = start(I) 

while ! done(I, state) 
    (i, state) = next(I, state) 

    if i == "fourth" 
     splice!(I, state - 1) 
     print("Delete element i=$(state - 1)\n") 
     state = state - 1 
     continue 
    end 

    print("Got: i=$i state=$state\n") 
end 

出力:

Got: i=first state=2 
Got: i=second state=3 
Got: i=third state=4 
Delete element i=4 

しかし、確かに、それは読むのは簡単でも書くのも簡単ではありません。それを反復しながら、ベクトルから要素を削除する "ジュリアン"の方法はありますか?あるいは、ある種の関数呼び出しによって明示的にサポートされている推奨データ構造はありますか?

+0

、削除されるべきであるすべてのインデックス、例えばを生成イテレータで一度だけdeleteat!を呼び出す方が良いです!(I) 'あなたが探しているものに近づく? [ええ、これはほうれん草と関係があるかどうか疑問に思う] – rickhg12hs

+0

@ rickhg12hs笑、残念ながら私が必要なものではありません。どのような位置であっても、ベクトルから要素を削除できるようにする必要があります。 – lama12345

答えて

3

解決方法1:shift!push!

julia> I = Vector{String}(["first", "second", "third", "fourth", "fifth"]); 
julia> Inew = Vector{String}(0); 
julia> while !isempty(I) 
     i = shift!(I); 
     if i == "fourth"; println("Skipped $i"); 
     else println("Got: i = $i"); push!(Inew, i); 
     end 
     end 
Got: i = first 
Got: i = second 
Got: i = third 
Skipped fourth 
Got: i = fifth 

julia> show(Inew) 
String["first", "second", "third", "fifth"] 


を使用して解決策2:これは新しいことから、必ずしも、より効率的ではないことに注意してください、しかしsplice!

julia> I = Vector{String}(["first", "second", "third", "fourth", "fifth"]); 
julia> i = 1; 
julia> while i <= length(I) 
     if I[i] == "fourth"; splice!(I,i); 
     else i += 1; 
     end 
     end 
julia> show(I) 
String["first", "second", "third", "fifth"] 

を使用してメモリはのために割り当てられますとにかく(サイズが変更されているため)にスプライスするたびにと表示されます。


解決方法3:(すなわち "ワンライナー")findindeleteat!を使用して:

julia> I = Vector{String}(["first", "second", "third", "fourth", "fifth"]); 
julia> deleteat!(I, findin(I, ["second", "fourth"])) 
3-element Array{String,1}: 
"first" 
"third" 
"fifth" 

、あなたが本当に任意の他の中間のアクションを実行する必要がない場合(たとえば、要素を特定して削除するだけの場合は、これはおそらく方法です。


さらにとりとめ:また

は、forループを経由してこれを行うには、あなたの試みについて:(任意の言語で)forループで反復鉄則は状態ということですを反復している変数のうち、は変更されません。このルールを守らないと、通常、最悪の場合には最良の場合のエラー、未定義の動作、サイレントエラーが発生します。変数の状態が変更されることになっている場合は、 'forループ'反復を調べるのではなく、より一般的なwhileループでは一貫性のある状態を仮定しません。

e.e.e.あなたがここで行ったことは正しいアプローチであり、forループを含むものを探すべきではありません。 (そして、あなたが見つけた場合は、その悪いコードを考えて、それだけで残してください:p)。しかし、そうですね、それをやっているより良い方法がありました。しかし、実際にはforループがjuliaに依存しているインタフェースを明示的に指定しているため、基本的にはホイールを再発見することに注意してください。私。次のコード:

for i in MyCollection; print("$i "); end 

は、本質的に内部的に同等のものとして翻訳さ:splice!何度も呼び出す

state = start(MyCollection) 
while !done(MyCollection, state) 
    (i, state) = next(MyCollection, state) 
    print("$i ") 
end 

+0

ありがとうございました。私の2番目の方法は、私が探していたものです。簡単に目には、新しい配列を作成し、それを繰り返しながら1つまたは複数の要素を削除することはありません。完璧な:) – lama12345

1

は大きな配列のために非常に遅いです:

function d!(I, s) 
    i = 1 
    while i <= length(I) 
     if I[i] == s; splice!(I,i); 
     else i += 1; 
     end 
    end 
end 

function t() 
    I = rand(1:10, 1000000) 
    s = 1 
    d!(I,s) 
    I 
end 

julia> @btime t() 
6.752 s (2 allocations: 7.63 MiB) 
899975-element Array{Int64,1}: 
... 

私がしたいのかわからないんだけど、 `ポップん

function d2!(I, s) 
    deleteat!(I, (i for i in eachindex(I) if I[i] == s)) 
end 

function t2() 
    I = rand(1:10, 1000000) 
    s = 1 
    d2!(I,s) 
    I 
end 

julia> @btime t2() 
15.889 ms (8 allocations: 7.63 MiB) 
900414-element Array{Int64,1}: 
... 
関連する問題