【问题标题】:How to find the index of the last maximum in julialang?如何找到julialang中最后一个最大值的索引?
【发布时间】:2017-11-04 17:15:55
【问题描述】:

我有一个包含重复非负整数的数组,例如A=[5,5,5,0,1,1,0,0,0,3,3,0,0]。我想在A 中找到最后一个最大值的位置。这是最大的索引i,使得所有jA[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));

有没有更好的办法?

【问题讨论】:

  • 如果您想要一个快速的解决方案,您可能应该在 Base 中编写一个与 findmax 完全相同的自定义函数,但将 if ai > m 替换为 if ai >= m。使用标准函数你可以写length(A)+1-indmax(reverse(A)),缺点是它执行A的副本。
  • Alex Arslan 刚刚在 Slack 上告诉我,0.7 有一个 Iterators.reverse 函数可以创建一个视图。
  • @MichaelK.Borregaard Iterators.reverse 不支持 indmax。 (ERROR: MethodError: no method matching keys(::Base.Iterators.Reverse{String}). Slack 是公开的?
  • 啊,对。是的,但你需要一个邀请。我想如果你去 slackinvite.julialang.org 你可以申请一个。

标签: julia


【解决方案1】:
length(A) - indmax(@view A[end:-1:1]) + 1

应该很快,但我没有对其进行基准测试。

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

【讨论】:

    【解决方案2】:

    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
    

    【讨论】:

    • 至少在 0.6 中,保持和更新 maxval 值比每次迭代进行两次索引查找要快。戴上@inbounds 似乎也有帮助。
    • @DNF 是的,你是对的。并不是说这里真的很重要,但我调整了帖子。
    • 我刚才提到它是因为你谈到了最快的方法。这些更改为我减少了近 40% 的运行时间。
    【解决方案3】:

    我尝试了@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
    

    【讨论】:

    • 你能报告时间吗? :-)
    • 是的,我做到了——大约 17 到 3 秒。 @crstnbr 的解决方案可能是您可以编程的最有效的解决方案 - 我的解决方案只是简写,它包含类似的算法 + 更多计算,因此速度较慢。
    【解决方案4】:

    Michael 的解决方案不支持字符串 (ERROR: MethodError: no method matching view(::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 的 Float64 解决方案慢达 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
    

    Strings

    慢 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 解决方案更快,并且也适用于字符串(不适用于生成器)。 lastindmaxlastimax 有区别——第一个返回字节索引,第二个返回字符索引:

    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
    

    【讨论】:

      猜你喜欢
      • 2018-05-05
      • 2016-07-14
      • 2018-05-20
      • 2019-08-21
      • 1970-01-01
      • 2018-04-25
      • 2016-08-21
      • 2014-05-19
      • 2016-06-11
      相关资源
      最近更新 更多