我很新手 Julia,不知道如何删除数组中连续的重复元素。例如,如果你有这个数组:
`v=[8,8,8,9,5,5,8,8,1];`
我想获得向量v1,使其满足以下条件:
v1 = [8,9,5,8,1];
有人能帮忙吗?非常感谢。
我很新手 Julia,不知道如何删除数组中连续的重复元素。例如,如果你有这个数组:
`v=[8,8,8,9,5,5,8,8,1];`
v1 = [8,9,5,8,1];
有人能帮忙吗?非常感谢。
一个方法是定义:
function fastuniq(v)
v1 = Vector{eltype(v)}()
if length(v)>0
laste = v[1]
push!(v1,laste)
for e in v
if e != laste
laste = e
push!(v1,laste)
end
end
end
return v1
end
通过这个函数,您将获得以下内容:
julia> println(fastuniq(v))
[8,9,5,8,1]
但是,在处理数组时,需要决定元素是要进行深拷贝还是浅拷贝。对于整数而言,这并不重要。
for
循环中使用@inbounds
,可以帮助提高性能。push!
函数已经进行了优化,以便许多小的push!
操作不会频繁地进行内存分配。 - Dan Getzcopy
(取决于是否需要副本)。 - Scott JonesStatsBase.jl
中有一个名为rle
的函数(Run-length encoding),可以实现这个功能。rle
中一个潜在的 bug:一个空向量会导致异常(在访问第一个元素之前没有检查)。 - Dan Getzinverse_rle(rle(v)...) == v
仍应该起作用。 - Dan Getzfunction notsofastunique(v)
return [v[1]; v[2:end][v[2:end] .!= v[1:end-1]]]
end
>println(notsofastunique(v))
[8,9,5,8,1]
lag(a, n=1) = append!(fill(NaN, n), a[1:(end-n)]); v[v .!= lag(v)]
同样的意思,但可能更清晰。 - ivo Welch为了达到 @niczky12 的简洁解决方案的目标,以下代码使用了 Iterators.jl
包(非常有用且正在逐步迁移到 Base 库中)。
using Iterators # install with Pkg.add("Iterators")
neatuniq(v) = map(first,filter(p->p[1]!=p[2],partition(chain(v,[nothing]),2,1)))
虽然没有进行过任何基准测试,但它应该没问题(但比较长的for
循环函数要慢一些)。
为了练习而已...
这里有另一个小函数可用于执行此操作,该函数仅适用于非负值(包括0)。
function anotherone(v)
v1 = zeros(eltype(v),length(v))
v1[1]=v[1]+1
for e = 2:length(v)
if v[e] != v[e-1]
v1[e] = v[e]+1
end
end
return v1[find(v1)]-1
end
编辑:
根据评论中的输入,添加了另一个版本。我认为这个版本应该更快,也许你可以测试一下 :) 这个版本也适用于负数。
function anotherone(v)
v1 = falses(length(v))
v1[1]=true
for e = 2:length(v)
if v[e] != v[e-1]
v1[e] = true
end
end
return v[v1]
end
v1
设置为逻辑数组(v1 = falses(length(v))
),然后在分配元素的位置将其设置为true。现在你可以简单地返回v[v1]
,它将适用于所有值和元素类型。 - mbauman
1
。 - niczky12