我想迭代列表并偶尔删除所述列表的项目。在玩具示例下面:
function delete_item!(myarray, item)
deleteat!(myarray, findin(myarray, [item]))
end
n = 1000
myarray = [i for i = 1:n];
for a in myarray
if a%2 == 0
delete_item!(myarray, a)
end
end
然而我收到错误:
BoundsError: attempt to access 500-element Array{Int64,1} at index [502]
如何解决(尽可能高效)?
其他信息。以上看起来似乎是一个愚蠢的例子,在我原来的问题中,我有一个代理商列表进行交互。因此,我不确定迭代副本是否是最佳解决方案。例如:
#creating my agent
mutable struct agent <: Any
id::Int
end
function delete_item!(myarray::Array{agent, 1}, item::agent)
deleteat!(myarray, findin(myarray, [item]))
end
#having my list of agents
n = 1000
myarray = agent[agent(i) for i = 1:n];
#trying to remove agents from list while having them interact
for a in myarray
#agent does stuff
if a.id%2 == 0 #if something happens remove
delete_item!(myarray, a)
end
end
答案 0 :(得分:3)
不幸的是,这个问题没有单一答案,因为最有效的方法取决于整个模型的逻辑(特别是其他代理的操作取决于某些条目实际上是从数组中删除的事实)。
在大多数情况下,以下方法应该是最简单的(我要离开findin
这是低效的,但我知道你可能在myarray
中通常会有重复项:
n = 1000
myarray = [i for i = 1:n];
keep = trues(n)
for (i, a) in enumerate(myarray)
keep[i] || continue # do not process an agent that is marked for deletion
if a%2 == 0 # here application logic might also need to check keep in some cases
keep[findin(myarray, [a])] = false
end
end
myarray = myarray[keep]
如果由于某种原因你真的需要在每次迭代中删除myarray
的元素,那么你将如何做到这一点:
n = 1000
myarray = [i for i = 1:n];
i = 1
while i <= length(myarray)
a = myarray[i]
if a%2 == 0
todelete = findin(myarray, [a])
i -= count(x -> x < i, todelete) # if myarray has duplicates of a you have to move the counter back
deleteat!(myarray, todelete)
else
i += 1
end
end
一般情况下,您提供的代码不会非常快(例如,如果您知道myarray
不包含重复项,则可以更加简单 - 我想您可以这样做。)
编辑:如果您知道没有重复项,可以使用以下方法实现这两个版本(您只需使用代理的索引 - 请注意我们也可以避免不必要的检查):
n = 1000
myarray = [i for i = 1:n];
keep = trues(n)
for (i, a) in enumerate(myarray)
if a%2 == 0 # here application logic might also need to check keep in some cases
keep[i] = false
end
end
myarray = myarray[keep]
如果由于某种原因你真的需要在每次迭代中删除myarray
的元素,那么你将如何做到这一点:
n = 1000
myarray = [i for i = 1:n];
i = 1
while i <= length(myarray)
a = myarray[i]
if a%2 == 0
deleteat!(myarray, i)
else
i += 1
end
end