如何找到julialang中最后一个最大值的索引?

如何找到julialang中最后一个最大值的索引?,julia,Julia,我有一个包含重复非负整数的数组,例如,A=[5,5,5,0,1,1,0,0,0,3,3,0,0]。我想在A中找到最后一个最大值的位置。这是所有j的最大索引A[i]>=A[j]。在我的示例中,i=3 我试图找到A的所有最大值的索引,然后找到这些索引的最大值: A = [5,5,5,0,1,1,0,0,0,3,3,0,0]; Amax = maximum(A); i = maximum(find(x -> x == Amax, A)); 有更好的方法吗?那么findlast(A.==maxi

我有一个包含重复非负整数的数组,例如,
A=[5,5,5,0,1,1,0,0,0,3,3,0,0]
。我想在
A
中找到最后一个最大值的位置。这是所有
j
的最大索引
A[i]>=A[j]
。在我的示例中,
i=3

我试图找到
A
的所有最大值的索引,然后找到这些索引的最大值:

A = [5,5,5,0,1,1,0,0,0,3,3,0,0];
Amax = maximum(A);
i = maximum(find(x -> x == Amax, A));
有更好的方法吗?

那么
findlast(A.==maximum(A))
呢(当然在概念上与您的方法类似)

最快的事情可能是显式循环实现,如下所示:

function lastindmax(x)
   k = 1
   m = x[1]
   @inbounds for i in eachindex(x)
       if x[i]>=m
           k = i
           m = x[i]
       end
   end
   return k
end
应该很快,但我没有进行基准测试


编辑:我应该注意到,根据定义@crstnbr的解决方案(从头开始编写算法)更快(小戴的回答中显示了更快的速度)。这是一个使用julia内置数组函数的尝试。

Michael的解决方案不支持字符串(
错误:MethodError:没有方法匹配视图(::String,::StepRange{Int64,Int64})或序列,因此我添加了另一个解决方案:

julia> lastimax(x) = maximum((j,i) for (i,j) in enumerate(x))[2]
julia> A="abžcdž"; lastimax(A)  # unicode is OK
6
julia> lastimax(i^2 for i in -10:7)
1
如果您更喜欢不捕获空序列的异常:

julia> lastimax(x) = !isempty(x) ? maximum((j,i) for (i,j) in enumerate(x))[2] : 0;
julia> lastimax(i for i in 1:3 if i>4)
0
简单(!)基准:

这比Michael的浮动64解决方案慢了10倍:

julia> mlastimax(A) = length(A) - indmax(@view A[end:-1:1]) + 1;
julia> julia> A = rand(Float64, 1_000_000); @time lastimax(A); @time mlastimax(A)
  0.166389 seconds (4.00 M allocations: 91.553 MiB, 4.63% gc time)
  0.019560 seconds (6 allocations: 240 bytes)
80346
(我很惊讶)对于Int64,它的速度是的2倍

julia> A = rand(Int64, 1_000_000); @time lastimax(A); @time mlastimax(A)
  0.015453 seconds (10 allocations: 304 bytes)
  0.031197 seconds (6 allocations: 240 bytes)
423400
对于字符串2-3倍

julia> A = ["A$i" for i in 1:1_000_000]; @time lastimax(A); @time   mlastimax(A)
  0.175117 seconds (2.00 M allocations: 61.035 MiB, 41.29% gc time)
  0.077098 seconds (7 allocations: 272 bytes)
999999
编辑2: @crstnbr解决方案速度更快,也适用于字符串(不适用于生成器)。
lastindmax
lastimax
之间存在差异-第一个返回字节索引,第二个返回字符索引:

julia> S = "1š3456789ž"
julia> length(S)
10
julia> lastindmax(S)  # return value is bigger than length
11
julia> lastimax(S)  # return character index (which is not byte index to String) of last max character
10

julia> S[chr2ind(S, lastimax(S))]
'ž': Unicode U+017e (category Ll: Letter, lowercase)

julia> S[chr2ind(S, lastimax(S))]==S[lastindmax(S)]
true

我尝试了@Michael的解决方案和@crstnbr的解决方案,发现后者更快

a = rand(Int8(1):Int8(5),1_000_000_000)

@time length(a) - indmax(@view a[end:-1:1]) + 1 # 19 seconds
@time length(a) - indmax(@view a[end:-1:1]) + 1 # 18 seconds


function lastindmax(x)
   k = 1
   m = x[1]
   @inbounds for i in eachindex(x)
       if x[i]>=m
           k = i
           m = x[i]
       end
   end
   return k
end

@time lastindmax(a) # 3 seconds
@time lastindmax(a) # 2.8 seconds

如果您想要一个快速的解决方案,您可能应该在Base中编写一个与
findmax
完全相同的自定义函数,但将
If ai>m
替换为
If ai>=m
。使用标准函数可以编写
length(A)+1-indmax(reverse(A))
,缺点是它执行
A
的副本。Alex Arslan刚刚告诉我0.7有一个
迭代器。reverse
函数创建视图。@MichaelK.Borregaard迭代器.reverse不支持indmax。(
ERROR:MethodError:no方法匹配键(::Base.Iterators.Reverse{String})
。Slack是公共的?啊,是的。是的,但是你需要一个邀请。我想如果你去slackinvite.julialang.org,你可以申请一个。至少在0.6版本中,保存和更新一个
maxval
值要比每次迭代查找两个索引更快。添加
@inbounds
似乎也有帮助。@DNF是的,你是对的。否这并不重要,但我调整了帖子。我之所以提到它,是因为你谈到了最快的方法。这些更改为我减少了近40%的运行时间。你能报告时间吗?:-)对,我做了-它们大约是17到3秒@crstnbr的解决方案可能是您可以编程的最有效的方案-我的解决方案只是简写,它包括这样的算法+更多的计算,因此速度较慢。
a = rand(Int8(1):Int8(5),1_000_000_000)

@time length(a) - indmax(@view a[end:-1:1]) + 1 # 19 seconds
@time length(a) - indmax(@view a[end:-1:1]) + 1 # 18 seconds


function lastindmax(x)
   k = 1
   m = x[1]
   @inbounds for i in eachindex(x)
       if x[i]>=m
           k = i
           m = x[i]
       end
   end
   return k
end

@time lastindmax(a) # 3 seconds
@time lastindmax(a) # 2.8 seconds