【问题标题】:Two dimensional array processing in RubyRuby 中的二维数组处理
【发布时间】:2019-09-08 11:37:24
【问题描述】:

我有一个整数值的二维数组。我想以最有效的方式处理数组。处理逻辑是:

如果 summary[row][col] 大于 summary[col][row],则 summary[row][col] -= summary[col][row] 反之亦然。如果两者相等,则使两个位置都为零。基本上就是计算两个位置的绝对差。

这是我建立的逻辑。有没有一种更简洁、更有效的方法来使用 Array 函数?

  row_ix = 0
  summary.each do |row|
    col_ix = 0
    row.each do |row_to_col_amt|
      if row_ix == col_ix
        col_ix += 1
        next
      end
      col_to_row_amt = summary[col_ix][row_ix]
      if row_to_col_amt >  col_to_row_amt
        summary[row_ix][col_ix] -= col_to_row_amt
        summary[col_ix][row_ix] = 0
      elsif row_to_col_amt <  col_to_row_amt
        summary[col_ix][row_ix] -= row_to_col_amt
        summary[row_ix][col_ix] = 0
      else
        summary[row_ix][col_ix] = 0
        summary[col_ix][row_ix] = 0
      end
      col_ix += 1
    end
    row_ix += 1
  end

【问题讨论】:

    标签: ruby multidimensional-array


    【解决方案1】:

    如果我理解了这个问题。

    ary 应该是一个方阵,因此 (x,y) 和 (y,x) 之间存在 1 对 1 的关系。因为在对角线上ary(x, y) == ary(y, x) 总是正确的,所以我保持不变(或者很容易将它设置为0)。

    所以,给定矩阵:

    ary = 
          [
            [1,  5,  5,  1, 5],
            [1,  1,  1,  1, 1],
            [1,  1,  1,  1, 1 ],
            [1,  1,  1,  1, 1 ],
            [5,  10, 10,  1, 10]
          ]
    

    让我们定义一个返回上三角形索引的方法,不包括对角线:

    def top_triangle_idxs(ary)
      n = ary.size - 1
      res = []
      (0..n).each do |m|
        (1..n).each do |n|
          res << [m,n] unless m == n || m > n
        end
      end
      res
    end
    

    所以,对于这种情况:

    idxs = top_triangle_idxs(ary)
    #=> [[0, 1], [0, 2], [0, 3], [0, 4], [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
    

    现在,让我们迭代 idxs 执行逻辑:

    idxs.each do |x,y|
      ary[x][y] -= ary[y][x] if ary[x][y] > ary[y][x]
      ary[y][x] -= ary[x][y] if ary[x][y] < ary[y][x]
      ary[x][y] = ary[y][x] = 0 if ary[x][y] == ary[y][x]
    end
    

    结果:

    ary.each(&method(:p))
    # [1, 4, 4, 0, 0]
    # [1, 1, 0, 0, 1]
    # [1, 0, 1, 0, 1]
    # [0, 0, 0, 1, 0]
    # [0, 9, 9, 0, 10]
    


    使用Enumerable#each_with_indexEnumerable#each_with_object 可以获得相同的结果,但要构建一个新矩阵:
    res = ary.each_with_index.with_object(Array.new(ary.size) { [] }) do |(row, x), new_ary|
      row.each_with_index do |e, y|
        new_ary[x][y] = e
        new_ary[x][y] = e - ary[y][x] if ary[x][y] > ary[y][x]
        new_ary[x][y] = 0 if e == ary[y][x] && x != y
      end
    end
    

    【讨论】:

    • 谢谢,是的,它是一个方阵。感谢您的解决方案。我想知道是否有更简单的解决方案,涉及到reduce、map等数组函数,以便可以减少自定义代码
    猜你喜欢
    • 2014-07-13
    • 1970-01-01
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多