【问题标题】:Ruby - Compare arrays and get index based on conditionRuby - 比较数组并根据条件获取索引
【发布时间】:2020-12-07 13:00:06
【问题描述】:

我有两个数组

array_input = %w[one two three two]
array_compare = %w[one two three four five]

如果值存在于输入数组中,我想从 array_compare 数组中提取“最高”索引。所需的输出是2,因为three 存在于输入数组和compare 数组中。

我试过了

val = nil
array_compare.reverse_each do |v|
  val = v and break if array_input.include? v
end

但它没有设置 val。

【问题讨论】:

    标签: arrays ruby set compare


    【解决方案1】:

    我刚刚在 irb 中执行(复制和粘贴)您的代码,之后val 是“三”。之后你真的检查了val,即

    p val
    

    ?这里是a screenshot of my transscript

    【讨论】:

    • 这不是答案。
    • @CarySwoveland :我认为这是一个答案,因为它解释(并证明)原始代码很好,并证明变量具有预期值。我承认这个答案太短了,它也可以是一个评论。我没有展示如何获得结果的替代实现,因为没有被问到。
    【解决方案2】:

    如果我理解正确,

    从 array_compare 数组中提取“最高”索引,如果该值存在于输入数组中,

    这可能是一种选择:

    array_compare.map.with_index { |e, id| id if array_input.include? e }.compact.max #=> 2
    

    如果array_compare = %w[one two three four five three],则返回5

    【讨论】:

      【解决方案3】:

      将用于查找的数组转换为set,以便更快地查找。
      从您正在搜索最大索引的数组末尾进行迭代(正如您正确地做的那样),也是为了速度。由于在找到最后一个匹配元素之前所有无用的查找,从数组开头迭代并选择最大索引的解决方案通常较慢。下面的方法会在第一次成功匹配时快速停止。
      最后,更正最大索引,因为 array_compare.reverse.each_with_index 返回 reversed 数组的索引。
      生成的代码可能比许多其他答案更长,但它既简单又快速:

      require 'set'
      array_input = %w[one two three two]
      array_compare = %w[one two three four five]
      set_input = array_input.to_set
      i_max = nil
      array_compare.reverse.each_with_index { |x, i| i_max = i and break if set_input.include? x }
      
      # correct the index to count from the beginning of 
      # array_compare, not from the end:
      i_max = array_compare.length - i_max - 1;
      
      puts i_max; # prints: 2
      

      另请参阅:

      Array.include?比较慢。此外,如果您只需要一个哈希值进行查找,请考虑使用一个集合:https://stackoverflow.com/a/411164/967621

      更多关于数组、集合和哈希的速度比较(带有基准):Advantages of Set in ruby

      【讨论】:

        【解决方案4】:

        可以写

        array_compare.rindex { |e| array_input.include?(e) }
          #=> 2
        

        但这需要对array_compare 的每个元素(从最后一个元素开始)线性搜索array_input,直到找到匹配项。更好的是以下。

        array_compare.rindex((array_compare & array_input).last)
          #=> 2
        

        步骤如下。

        a = array_compare & array_input
          #=> ["one", "two", "three"]
        

        Array#&。请注意,“订单保留自原始数组 [array_compare]。”。这种一次性操作将非常快,因为它是在 C 中实现的。继续,

        e = a.last
          #=> "three" 
        array_compare.rindex(e)
          #=> 2
        

        Array#rindex

        【讨论】:

          【解决方案5】:

          我能想到的最高效的解决方案是:

          def find_last_index(set_input, array_compare)
            (array_compare.length - 1).downto(0) do |i|
              return i if set_input.include?(array_compare[i])
            end
          end
          

          请注意,参数set_inputSet,而不是Array。将数组转换为集合是有意义的,但前提是您想使用同一个集合多次调用find_last_index。否则,将数组转换为集合 (to_set) 的过程比使用 Set#include? 而不是 Array#include? 获得的时间要长。所以如果你只想使用一次find_last_index,你不应该调用find_last_index(array_input.to_set, array_compare),而是使用这个完全不使用集合的版本:

          def find_last_index(array_input, array_compare)
            (array_compare.length - 1).downto(0) do |i|
              return i if array_input.include?(array_compare[i])
            end
          end
          

          您可能希望看到this benchmark 对此问题的不同解决方案。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-07-30
            • 1970-01-01
            • 1970-01-01
            • 2021-12-10
            • 1970-01-01
            • 1970-01-01
            • 2014-09-26
            • 2018-06-22
            相关资源
            最近更新 更多