使用Ruby优化数组循环

时间:2018-11-28 11:43:29

标签: arrays ruby

我有(m =行-1,n = cols-1)维矩阵。

然后将 i 传递给方法,该方法将以以下方式返回数组(由i <= m,n提供)

假设n = 0,因此对于4x4矩阵,它将返回边界元素的位置。

不要在下面将其视为ruby语法,只能获得流量。

square = [[i,i] -> [i, m-i] -> [n-i, m-1] -> [n-i, i] -> [i,i]]

(上面没有重复数据)

我通过设置参数以递归的方式实现了上述目标,但我需要更简单/优化的技巧。

更新-适用于用户sawa

arr = [*1..16].each_slice(4).to_a
m,n = arr.length-1, arr[0].length-1

loop_count = 0

output = [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0], [4, 1], [4, 2], [3, 2], [2, 2], [1, 2], [0, 2], [0, 1]]

loop_count = 1

output = [[1, 1], [2, 1], [2, 2], [1, 2]]

3 个答案:

答案 0 :(得分:1)

我最终得到了这种解决方案,但是我认为还有更好的方法。

首先定义一种方法来打印由索引映射的矩阵,只是检查结果ID是否正确:

def print_matrix(n,m)
  range_n, range_m = (0..n-1), (0..m-1)
  mapp = range_m.map { |y| range_n.map { |x| [x, y] } }
  mapp.each { |e| p e }
  puts "-" * 8 * n
end

然后定义一个方法,该方法返回从循环s开始的帧(其中0是外部帧):

def frame (n, m, s = 0)
  res = []
  return res if (s >= n/2 and s >= m/2) and (n.even? or m.even?)
  (s..n-s-1).each { |x| res << [x,s] }
  (s..m-s-1).each { |y| res << [res.last[0], y] }
  (res.last[0].downto s).each { |x| res << [x, res.last[1]] }
  (res.last[1].downto s).each { |y| res << [res.last[0], y] }
  res.uniq
end

现在,调用方法并检查输出:

n, m, loops = 4, 4, 1
print_matrix(n,m)
frame(n, m, loops)

# [[0, 0], [1, 0], [2, 0], [3, 0]]
# [[0, 1], [1, 1], [2, 1], [3, 1]]
# [[0, 2], [1, 2], [2, 2], [3, 2]]
# [[0, 3], [1, 3], [2, 3], [3, 3]]
# --------------------------------
# [[1, 1], [2, 1], [2, 2], [1, 2]]

答案 1 :(得分:1)

在这里,我们可以使用Matrix方法来发挥优势,特别是Matrix::buildMatrix#minorMatrix#[]

代码

require 'matrix'

def border_indices(nrows, ncols, i)
  m = Matrix.build(nrows, ncols) { |r,c| [r,c] }.minor(i..nrows-1-i, i..ncols-1-i)
  [[1,0,m.row_count-1], [0,1,m.column_count-1],
   [-1,0,m.row_count-1], [0,-1,m.column_count-2]].
    each_with_object([[0,0]]) do |(x,y,n),a|
      n.times { a << [a.last.first+x, a.last.last+y] }
    end.map { |i,j| m[i,j] }
end

示例

nrows = 5
ncols = 6

border_indices(nrows, ncols, 0)
  #=> [[0, 0], [1, 0], [2, 0], [3, 0],
  #    [4, 0], [4, 1], [4, 2], [4, 3], [4, 4],
  #    [4, 5], [3, 5], [2, 5], [1, 5],
  #    [0, 5], [0, 4], [0, 3], [0, 2], [0, 1]]
border_indices(nrows, ncols, 1)
  #=> [[1, 1], [2, 1],
  #    [3, 1], [3, 2], [3, 3],
  #    [3, 4], [2, 4],
  #    [1, 4], [1, 3], [1, 2]]
border_indices(nrows, ncols, 2)
  #=> [[2, 2], [2, 3]]

说明

考虑计算border_indices(5, 6, 1)

nrows = 5
ncols = 6
i = 1
mat = Matrix.build(nrows, ncols) { |r,c| [r,c] }
  #=> Matrix[[[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5]],
  #          [[1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5]],
  #          [[2, 0], [2, 1], [2, 2], [2, 3], [2, 4], [2, 5]],
  #          [[3, 0], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5]],
  #          [[4, 0], [4, 1], [4, 2], [4, 3], [4, 4], [4, 5]]]
m = mat.minor(i..nrows-1-i, i..ncols-1-i)
  #=> mat.minor(1..3, 1..4)
  #=> Matrix[[[1, 1], [1, 2], [1, 3], [1, 4]],
  #          [[2, 1], [2, 2], [2, 3], [2, 4]],
  #          [[3, 1], [3, 2], [3, 3], [3, 4]]]
b = [[1,0,m.row_count-1], [0,1,m.column_count-1],
     [-1,0,m.row_count-1], [0,-1,m.column_count-2]]
  #=> [[1, 0, 2], [0, 1, 3], [-1, 0, 2], [0, -1, 2]]
c = b.each_with_object([[0,0]]) do |(x,y,n),a|
      n.times { a << [a.last.first+x, a.last.last+y] }
    end
  #=> [[0, 0], [1, 0],
  #    [2, 0], [2, 1], [2, 2],
  #    [2, 3], [1, 3],
  #    [0, 3], [0, 2], [0, 1]]
c.map { |i,j| m[i,j] }
  #=> [[1, 1], [2, 1],
  #    [3, 1], [3, 2], [3, 3],
  #    [3, 4], [2, 4],
  #    [1, 4], [1, 3], [1, 2]]

请注意,在计算c时,a.last是添加到正在构造的数组(a.last = [a.last.first, a.last.last])中的最后一对索引。

答案 2 :(得分:1)

以下情况适用于m == nm != n情况。

我希望所有人都会考虑下面的矩阵变量代表(二维数组)

def matrixRotation(matrix)
    m,n = matrix.length-1, matrix[0].length-1
    loop_count = [m,n].min/2
    0.upto(loop_count) do |i|
        indices = []
        i.upto(m-i) { |j| indices << [j, i] }
        i.upto(n-i) { |j| indices << [m-i, j] }
        i.upto(m-i) { |j| indices << [m-j, n-i] }
        i.upto(n-i) { |j| indices << [i, n-j] }
        puts "-------------- For Layer #{i+1} ---------------", nil
        indices = indices.uniq
        values = indices.map { |x| matrix[x[0]][x[1]] }
        puts 'indices:', indices.inspect, nil, 'values:', values.inspect
    end
end