【问题标题】:how to match the contents of two arrays and get corresponding index ruby如何匹配两个数组的内容并获得对应的索引ruby
【发布时间】:2015-05-22 05:13:38
【问题描述】:

原始问题:原始问题是如何迭代到嵌套循环 ruby​​ 中的下一个元素。答案教了一种惯用的方法来解决我的问题,它需要一个不同的问题,以便当用户在谷歌上搜索时,找到正确的东西

我有这个要求,其中有两个数组,每个数组都有唯一的值,按排序顺序。

array1 = [2,3,4,5,6,7] #can not have repeated values[2,2,3]
array2 = [2,5,7]

我想匹配两个数组的元素,并在找到匹配项时打印match found,以及两个数组的索引。这是工作正常的代码。

array1.each do |arr1|
  array2.each do |arr2|
    if (arr1==arr2)
      puts ("Match found element #{arr1} #{array1.index(arr1)} #{array2.index(arr2)}")
      #some code here to move to the next element in array 1 and array 2 and continue looping from there
    end
  end
end

但这并没有利用数据结构的独特性和以任何方式排序的质量。例如,在上面的例子中,当array1中的元素2匹配array2中的元素2时,array2中的元素2不应该继续尝试匹配array1的其他元素,并且array1 应该移到下一个。我知道有一个东西叫next。但我认为这只是返回下一个元素而不将迭代器移动到下一个元素?另外我必须移动到两个数组中的下一个。我该怎么做呢?

【问题讨论】:

    标签: arrays ruby


    【解决方案1】:

    如果你想在两个数组之间找到匹配的元素,只需使用&,如下所示:

    array1 = [2,3,4,5,6,7] #does not have repeated values[2,2,3] and the values are sorted
    array2 = [2,5,7]
    
    matches = array1 & array2
     => [2, 5, 7]
    

    要打印在每个数组中找到的匹配项和索引,只需像这样循环遍历匹配项数组:

    matches.each do |number|
      puts "Match found element #{number}"
      puts "array1 index=#{array1.rindex(number)}"
      puts "array2 index=#{array2.rindex(number)}"
    end
    
    Match found element 2
    array1 index=0
    array2 index=0
    Match found element 5
    array1 index=3
    array2 index=1
    Match found element 7
    array1 index=5
    array2 index=2
    

    【讨论】:

    • 感谢您的及时回复。我不知道我也可以这样做,但我的要求不仅仅是匹配,实际上我想获取元素匹配的两个数组的索引。例如,这将返回array1 index=0 array2 index=0,然后是array1 index=3 array2 index=1array1 index=5 array index=2。那我下一步该怎么做。我现在将编辑问题。
    • 在我的解决方案中,您不必移动到下一个元素。您首先找到两个数组中出现的数字。然后通过获取该字母的rindex 找到索引。 rindex 告诉你元素出现在数组中的索引。
    • 是的,明白了,谢谢。顺便说一句,matches=array1&array2 是如何工作的?
    • & 运算符将两个数组作为参数并返回两个数组包含的数字。因此,当您调用array1 & array2 时,它会返回一个包含两个数组中出现的数字的数组。示例:[1,2,3] & [1,3,5] 将返回 [1,3]
    • 酷,谢谢,我现在更喜欢 ruby​​。惯用代码摇滚!非常感谢
    【解决方案2】:

    对于您的代码,您只需要使用break 退出array2 循环,移动到array1 中的下一个元素。

    array2.each_with_index do |arr1, i1|
       array1.each_with_index do |arr2, i2|
         if (arr1==arr2)
           puts ("Match found element array1: #{arr1} #{i1} and array2: #{arr2} #{i2}")
           #if match element is found, exit from the current loop
           break
         end
       end
        end
    Match found element array1: 2 0 and array2: 2 0
    Match found element array1: 5 1 and array2: 5 3
    Match found element array1: 7 2 and array2: 7 5
    

    (array1 & array2).map{ |e| puts "Match found element #{e}" }
    Match found element 2
    Match found element 5
    Match found element 7
    

    【讨论】:

    • 不错的惯用方法,但我想获取元素匹配的两个数组的索引。例如这将返回array1 index=0 array2 index=0 then array1 index=3 array2 index=1 and array1 index=5 array index=2。那我下一步该怎么做。我现在将编辑问题。
    • 是的,这也有效,但它只是在 array1 中找到匹配项时移动到下一个。对于array1 的下一个元素,它将再次从array2 的第0 个元素开始。我想优化代码,它优化但不是两个循环。顺便说一句,使用 array1 和 array2 的惯用代码是如何工作的?它是否在内部进行了一些优化?
    • 如果你改变两个数组的位置,你会得到更好的性能。
    • 你的意思是用array2改变array1?但这只是一个示例代码。我永远不知道,array1 是否包含更多元素或 array2。可能我需要为此使用大小/长度方法并继续。另请参阅我在已接受答案中的最后评论。感谢您的时间和帮助。
    【解决方案3】:

    这是另一种方式:

    array1 = [2,3,4,5,6,7]
    array2 = [2,5,7]
    
    h = array1.each_with_index.to_h
      #=> {2=>0, 3=>1, 4=>2, 5=>3, 6=>4, 7=>5} 
    
    array2.each_with_index.with_object({}) { |(v,i),g| g[v] = [h[v],i] if h.key?(v) }
      #=> {2=>[0, 0], 5=>[3, 1], 7=>[5, 2]} 
    

    第二个表达式可以分解如下:

    e0 = array2.each_with_index
      #=> #<Enumerator: [2, 5, 7]:each_with_index> 
    

    我们可以通过将这个枚举器转换为数组来查看它的元素:

    e0.to_a
      #=> [[2, 0], [5, 1], [7, 2]] 
    
    e1 = e0.with_object({})
      #=> #<Enumerator: #<Enumerator: [2, 5,7]:each_with_index>:with_object({})> 
    e1.to_a
      #=> [[[2, 0], {}], [[5, 1], {}], [[7, 2], {}]]
    

    枚举器e 的元素被传递给块并由Enumerator#each 分配给块变量。第一个(使用Enumerator#next 获得)是:

    (v,i),g = e1.next
      #=> [[2, 0], {}] 
    v #=> 2 
    i #=> 0 
    g #=> {} 
    

    我们现在可以执行代码块了:

    g[v] = [h[v],i] if h.key?(v)
      #=> g[2] = [h[2],0] if h.key(v)
      #   g[2] = [0,0] if true
    

    e1 的下一个元素现在被传递给块:

    (v,i),g = e1.next
      #=> [[5, 1], {}] 
    v #=> 5 
    i #=> 1 
    g #=> {2=>[0, 0]} 
    g[v] = [h[v],i] if h.key?(v)
      # g[5] = [h[5], 1] if h.key?(5)
      # g[5] = [3, 1] if true
    
    g #=> {2=>[0, 0], 5=>[3, 1]} 
    

    e1的最后一个元素的计算类似。

    【讨论】:

    • 很好,你能解释一下代码array2.each_with_index.with_object({}) { |(v,i),g| g[v] = [h[v],i] if h.key?(v) }吗?我不明白这里的块
    • 我添加了一个解释。
    • 嘿,这解释了一切。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-01
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多