julia - 迭代列表时删除列表项时的 Julia BoundsError
问题描述
我想遍历一个列表并偶尔删除所述列表中的项目。下面是一个玩具示例:
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
解决方案
不幸的是,这个问题没有单一的答案,因为最有效的方法取决于整个模型的逻辑(特别是其他代理的动作是否取决于实际从数组中删除某些条目的事实)。
在大多数情况下,以下方法应该是最简单的(我要离开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
推荐阅读
- c# - 如何在 LINQPad 中创建 FTP 连接
- php - 我有两个数组。在第一个数组中我有一些空值,我想用第二个数组更新这些空值
- android - 使用 else 语句在一个微调器中包含两个 Json 列表
- python - bin/python3:无法执行二进制文件:执行格式错误
- c# - 有没有办法使用 C# 更新 Google Cloud Datastore 的 index.yaml 文件
- blockchain - 在发送大量交易期间内存池溢出
- javascript - 如何将数据从一个对象插入到具有不同结构的另一个对象以生成第三个对象
- html - 是否可以在 CSS 中复制“div”?
- python-sphinx - 词汇表中的多个(嵌套)角色
- php - XSS 和回显