【问题标题】:What's the 'Ruby way' to iterate over two arrays at once一次遍历两个数组的“Ruby方式”是什么
【发布时间】:2011-04-04 13:10:58
【问题描述】:

更多的是语法好奇心而不是要解决的问题......

我有两个长度相等的数组,并且想同时对它们进行迭代 - 例如,在某个索引处输出它们的值。

@budget = [ 100, 150, 25, 105 ]
@actual = [ 120, 100, 50, 100 ]

我知道我可以使用 each_index 并像这样对数组进行索引:

@budget.each_index do |i|
  puts @budget[i]
  puts @actual[i]
end

有没有一种 Ruby 方法 可以更好地做到这一点? 这样的东西?

# Obviously doesn't achieve what I want it to - but is there something like this?
[@budget, @actual].each do |budget, actual|
  puts budget
  puts actual
end

【问题讨论】:

  • 两个数组的大小是否相等?
  • 是的 - 两者的长度相同

标签: ruby arrays iterator


【解决方案1】:

使用Array.zip 方法并传递一个块以依次迭代相应的元素。

【讨论】:

    【解决方案2】:
    >> @budget = [ 100, 150, 25, 105 ]
    => [100, 150, 25, 105]
    >> @actual = [ 120, 100, 50, 100 ]
    => [120, 100, 50, 100]
    
    >> @budget.zip @actual
    => [[100, 120], [150, 100], [25, 50], [105, 100]]
    
    >> @budget.zip(@actual).each do |budget, actual|
    ?>   puts budget
    >>   puts actual
    >> end
    100
    120
    150
    100
    25
    50
    105
    100
    => [[100, 120], [150, 100], [25, 50], [105, 100]]
    

    【讨论】:

    • '.each' 可以展开数组元素吗?我想知道还有多少 Ruby 我不知道:/
    • 如果要使用这样的表达式,最好在方法调用中使用括号,以防万一。 @budget.zip(@actual).each
    • @AboutRuby:在这种情况下,它是必需的!固定。
    • 当我看到这样的红宝石线条时,我把手举在空中,像冠军一样在房间里走来走去!
    • 这个规模吗?如果我有 2 个 10000 项数组,这是否需要创建一个 20,000 项数组?文档建议这样做。
    【解决方案3】:

    除了其他人所说的a.zip(b).each{|x,y| },您还可以说[a,b].transpose.each{|x,y| },这让我觉得有点对称。不过,可能没有那么快,因为您正在创建额外的 [a,b] 数组。

    【讨论】:

    • +1 transpose 的好处之一是,如果两个数组的长度不同,它会引发异常。
    【解决方案4】:

    还有另一种方法可以使用枚举器一次遍历两个数组:

    2.1.2 :003 > enum = [1,2,4].each
     => #<Enumerator: [1, 2, 4]:each> 
    2.1.2 :004 > enum2 = [5,6,7].each
     => #<Enumerator: [5, 6, 7]:each> 
    2.1.2 :005 > loop do
    2.1.2 :006 >     a1,a2=enum.next,enum2.next
    2.1.2 :007?>   puts "array 1 #{a1} array 2 #{a2}"
    2.1.2 :008?>   end
    array 1 1 array 2 5
    array 1 2 array 2 6
    array 1 4 array 2 7
    

    枚举器比上面使用的示例更强大,因为它们允许无限级数、并行迭代以及其他技术。

    【讨论】:

    • 有没有办法在上面显示的loop 中获取索引?
    【解决方案5】:

    与原始问题相关,用于迭代 不等 长度的数组,您希望值在其中循环,您可以使用

    [1,2,3,4,5,6].zip([7,8,9].cycle)
    

    Ruby 会给你

    [[1, 7], [2, 8], [3, 9], [4, 7], [5, 8], [6, 9]]
    

    这使您免于使用 zip 获得的 nil

    【讨论】:

      【解决方案6】:

      如果您正在处理数组,只需将两个数组压缩在一起就可以很好地工作。但是,如果您正在处理永无止境的枚举器,例如这些:

      enum1 = (1..5).cycle
      enum2 = (10..12).cycle
      

      enum1.zip(enum2) 失败,因为zip 试图评估所有元素并将它们组合起来。而是这样做:

      enum1.lazy.zip(enum2)
      

      lazy 可以让生成的枚举器进行惰性求值,从而为您省钱。

      【讨论】:

        【解决方案7】:

        妥协并使用#each_with_index 怎么样?

        include Enumerable 
        
        @budget = [ 100, 150, 25, 105 ]
        @actual = [ 120, 100, 50, 100 ]
        
        @budget.each_with_index { |val, i| puts val; puts @actual[i] }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-04-10
          • 1970-01-01
          • 2010-10-04
          • 2014-11-03
          • 2020-09-28
          • 2013-10-04
          • 2015-11-10
          • 1970-01-01
          相关资源
          最近更新 更多