【问题标题】:Multiply each element in array by all other elements in same array将数组中的每个元素乘以同一数组中的所有其他元素
【发布时间】:2013-12-24 20:12:32
【问题描述】:

我正在尝试在 Ruby 中创建一个时间表,其中给出一个整数,输出是该整数的时间表。

示例:times_table(5)

结果:

1   2   3   4   5
2   4   6   8  10   
3   6   9  12  15   
4   8  12  16  20   
5  10  15  20  25

到目前为止我有:

def times_table(rows)
  table_array = (1..rows).to_a

  table_array.each do |i|

end

times_table(5)

使用 table_array,我可以获得[1,2,3,4,5],但我需要将结果设为1 * 2 , 1 * 3, 1 * 4, 1 * 5, 2 * 1, 2 * 2, 2 * 3 等。基本上,我需要第一个元素与数组中的所有其他元素相乘,然后继续下一个元素。关于如何做到这一点的任何想法?

【问题讨论】:

    标签: ruby arrays enums


    【解决方案1】:

    在数学上,我更喜欢在该用例中使用Matrix

    关系是,您必须生成 n*n 矩阵,其中每个单元格都有关系 (c+1) * (r+1) 其中,c 表示 column-number 和 @987654324 @ 表示行数(考虑,0 索引矩阵)

    require 'matrix'
    def times_table(n)
      Matrix.build(n, n) { |r, c| (c+1)*(r+1) }
    end
    
    times_table(5)
    #=> Matrix[[1, 2, 3, 4, 5], [2, 4, 6, 8, 10], [3, 6, 9, 12, 15], [4, 8, 12, 16, 20], [5, 10, 15, 20, 25]]
    times_table(5).to_a
    #=> [[1, 2, 3, 4, 5],
     [2, 4, 6, 8, 10],
     [3, 6, 9, 12, 15],
     [4, 8, 12, 16, 20],
     [5, 10, 15, 20, 25]]
    

    【讨论】:

      【解决方案2】:

      另一种需要 ActiveSupport 的方式:

      def times_table(n)
        [*1..n].product([*1..n]).map { |arr| arr.reduce(:*) }.in_groups(n)  
      end
      

      因此,例如,times_table(5) 会返回

      => [[1, 2, 3, 4, 5],
         [2, 4, 6, 8, 10],
         [3, 6, 9, 12, 15],
         [4, 8, 12, 16, 20],
         [5, 10, 15, 20, 25]]
      

      您可以根据自己的喜好打印出来。

      更新:正如 Cary 指出的,in_groups 是 ActiveSupport 的一部分。这是上面的代码稍作修改,以便它可以与标准 Ruby 一起使用:

      def times_table(n)
        [*1..n].product([*1..n]).map { |arr| arr.reduce(:*) }.each_slice(n).to_a  
      end
      

      你也可以这样做:

      def times_table(n)
        Array.new(n) { |x| Array.new(n) { |y| (x+1)*(y+1) } }
      end
      

      【讨论】:

      • 如果in_groups 不熟悉(就像我一样),它是 ActiveSupport 的一部分。在这个和未来的答案中,您可能想放弃“......无论好坏”。这就像在说,“你可能不会喜欢这个,但是..”
      • 感谢卡里的建设性批评。尝试在 Stack Overflow 上自信地回答问题。 “无论好坏”我的意思是这是可以工作的紧凑代码,但可能不是解决问题的最有效方法。
      • 我认为提供替代解决方案是值得的,即使在您认为其他人提出的解决方案更好的情况下,因为它可能会为读者提供可以应用于未来其他问题的想法。在这种情况下,您可能会说:“这是替代方法,但我更喜欢在这种情况下使用 XXX。”
      【解决方案3】:

      我会这样做:

      def times_table(rows)
        table_rng = (1..rows)
        table_rng.each do |i|
          puts table_rng.map{|e| e*i }.join(" ")
        end
      end
      
      times_table(5)
      # >> 1 2 3 4 5
      # >> 2 4 6 8 10
      # >> 3 6 9 12 15
      # >> 4 8 12 16 20
      # >> 5 10 15 20 25
      

      更新(Cary Swoveland 的好建议)

      def times_table(rows)
        fmt = "%#{(rows*rows).to_s.size}d"
        table_rng = (1..rows)
        table_rng.each do |i|
          puts table_rng.map{|e| fmt % (e*i) }.join(' ')
        end
      end
      
      times_table(5)
      # >>  1  2  3  4  5
      # >>  2  4  6  8 10
      # >>  3  6  9 12 15
      # >>  4  8 12 16 20
      # >>  5 10 15 20 25
      

      【讨论】:

      • 啊,谢谢 Arup!这非常有效。感谢您的帮助。
      • to_a 可以删除。
      • @steenslag 感谢您的指点。它是由于复制粘贴而来的 :)
      • 也许稍微整理一下:width = (rows*rows).to_s.size,然后是puts table_rng.map{|e| "%#{width}d" % (e*i) }.join(' ')。我之所以提到这一点,部分原因是我注意到没有括号,第二个表达式的计算结果为("%#{width}d" % e)*i,我想我可能会继续下去。
      • @CarySwoveland 太棒了!我只是没有考虑格式!我喜欢你的方法,并感谢你帮助我改进答案。
      【解决方案4】:

      我会这样做:

      def times_table(rows, spaces=1)
        fmt = "%#{(rows*rows).to_s.size}d"
        (1..rows).each {|i| \
          puts (i..i*rows).step(i).map {|j| fmt % j}.join(' '*spaces)}
      end
      
      times_table(5,2)
      
      1   2   3   4   5
      2   4   6   8  10
      3   6   9  12  15
      4   8  12  16  20
      5  10  15  20  25  
      

      【讨论】:

      • 我的意思是[*1..rows].each_index.{..}
      猜你喜欢
      • 1970-01-01
      • 2015-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-28
      • 1970-01-01
      • 2013-11-08
      相关资源
      最近更新 更多