在Julia中删除数组中的元素

31

我在文档和论坛中漫游了一段时间,但没有找到一个内置的方法/函数来完成删除数组中元素的简单任务。是否有这样的内置函数?

我要求的是Python中list.remove(x)的等效函数。

这里是一个天真地从盒子中选择函数的例子:

julia> a=Any["D","A","s","t"]
julia> pop!(a, "s")
ERROR: MethodError: `pop!` has no method matching       
pop!(::Array{Any,1},     ::ASCIIString)
Closest candidates are:
  pop!(::Array{T,1})
  pop!(::ObjectIdDict, ::ANY, ::ANY)
  pop!(::ObjectIdDict, ::ANY)
  ...

这里提到要使用deleteat!,但是仍然不起作用:

julia> deleteat!(a, "s")
ERROR: MethodError: `-` has no method matching -(::Int64, ::Char)
Closest candidates are:
  -(::Int64)
  -(::Int64, ::Int64)
  -(::Real, ::Complex{T<:Real})
  ...

 in deleteat! at array.jl:621
6个回答

29
您也可以选择使用filter!
a = Any["D", "A", "s", "t"]
filter!(e->e≠"s",a)
println(a)

提供:

Any["D","A","t"]

这允许一次删除多个值,例如:
```python del a[0], b[1], c[2] ```
filter!(e->e∉["s","A"],a)

注意1:在Julia 0.5中,匿名函数速度更快,而在0.4中感受到的小惩罚不再是问题:-)。
注意2:上面的代码使用了unicode运算符。使用普通运算符:!=e∉[a,b]!(e in [a,b])

1
这是最好的解决方案。但对我来说,filter! 不起作用。只需要 filter 就可以了。所以如果我有数组 b = ["s","A"],我可以使用 filter(e->e∉b,a) 这个方法,它非常有效。 - pinq-
警告:如果您需要调用大量条件或需要重复调用filter!,它可能效率低下。如果您知道集合是唯一的,则setdiff!是更好的选择。如果您有一种方法来跟踪索引,那么您可以使用deleteat!()一次性删除所有内容。 - Nick Bauer

12

其他一些答案已经被Julia的最新版本所废弃。我目前(Julia 1.1.0)使用类似以下的代码:

Several of the other answers have been deprecated by more recent releases of Julia. I'm currently (Julia 1.1.0) using something like

function remove!(a, item)
    deleteat!(a, findall(x->x==item, a))
end

如果你想的话,也可以使用findfirst,但是如果a不包含item,它将无法正常工作。


1
谢谢!但感觉 Julia 的开发者们似乎尽可能地把它搞得更复杂了。 - Peter B
1
如果您在关键循环中使用此功能,请注意99%的资源可能正在使用findall()。如果需要使用此功能,最好保留一个IdDict映射项到其索引,然后当您想要删除它时,只需查找索引即可。 - Nick Bauer

9

根据使用情况,了解setdiff及其原地版本setdiff!也是很好的:

julia> setdiff([1,2,3,4], [3])
3-element Array{Int64,1}:
 1
 2
 4

请注意,它也会删除所有重复的元素,就像这个例子所示:
julia> setdiff!([1,2,3,4, 4], [3])
3-element Array{Int64,1}:
 1
 2
 4

2
您可以使用deleteat!findall来完成此操作(与Julia>1.0兼容)。
a=Any["D","A","s","t","s"]
deleteat!(a, findall(x->x=="s",a))

输出:

3-element Array{Any,1}:
"D"
"A"
"t"

0
最近的答案都很好。然而,使用查找函数find___来查找要删除的项并使用deleteat!()非常低效。我发现因为我使用了这个方法,我的代码执行所需时间比需要的时间长100倍!
另一种方法是创建一个项目及其索引的字典,这样只有在需要时才能简单地查找它们。
items # vector of items
itemindexes = IdDict(zip(items, eachindex(items))

todelete = Int[]

# do stuff and record indexes to delete with push!(todelete, <indexhere>)

sort!(todelete) # has to be in increasing order
deleteat!(items, todelete)

显然,一旦使用deleteat!,索引就变得无效,因此您需要更新它们。


0
我想补充一下,deleteat!() 可以通过索引从数组中删除一个项目。
julia>a = [1, 2, 3]
julia>deleteat(a, 3)
julia>display(a)
2-element Vector{Int64}:
 1
 2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接