我的第一次尝试是:
I = Vector{String}(["first", "second", "third", "fourth"])
for i in I
if i == "fourth"
splice!(I, 4)
end
print("$i\n")
end
最终出现在Bounds错误中:
BoundsError(String["first", "second", "third"], (5,))
然后我觉得它有点像'#34;手写"方式:
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
但是,那不容易阅读也不容易写。有没有" julian"从迭代中删除元素的方法?或者是否有任何推荐的数据结构通过某些函数调用显式支持它?
答案 0 :(得分:2)
解决方案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"]
但是,请注意,这不一定更有效,因为无论何时拼接 ,都会为I
分配新内存(因为它正在改变大小)。
解决方案3:使用findin
和deleteat!
(即“单行”):
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循环中,它不会假设一致的状态。 子>
<子> 即你在这里做的是正确的方法,你不应该寻找一个涉及for循环的方法。 (如果你确实碰巧找到了一个,那就考虑一下这个糟糕的代码而不管它:p)。但是,是的,有更好看的方式;然而值得注意的是,你所做的基本上是重新发现轮子,因为你明确了for循环实际上依赖于julia的界面。即以下代码: 子>
for i in MyCollection; print("$i "); end
<子> 基本上内部翻译为等效的: 子>
state = start(MyCollection)
while !done( MyCollection, state)
(i, state) = next(MyCollection, state)
print("$i ")
end
答案 1 :(得分:1)
对于大型数组,多次调用splice!
非常慢:
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}:
...
最好只使用迭代器调用deleteat!
一次,该迭代器产生应删除的所有索引,例如,
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}:
...