使用ruby类中的方法进行迭代

时间:2016-05-03 00:21:02

标签: ruby algorithm class iteration

类图像使用0和1的数组进行初始化。我有方法transform,这样

[[0,0,0],
 [0,1,0],
 [0,0,0]]

返回

[[0,1,0],
 [1,1,1],
 [0,1,0]]

我想实现方法blur(n),它使用transform迭代n次,例如使用

调用blur(2)
[[0,0,0,0,0,0,0,0,0],
 [0,0,0,0,0,0,0,0,0],
 [0,0,0,0,1,0,0,0,0],
 [0,0,0,0,0,0,0,0,0],
 [0,0,0,0,0,0,0,0,0]]

返回

[[0,0,0,0,1,0,0,0,0],
 [0,0,0,1,1,1,0,0,0],
 [0,0,1,1,1,1,1,0,0],
 [0,0,0,1,1,1,0,0,0],
 [0,0,0,0,1,0,0,0,0]]

我正在尝试迭代地使用变换来实现这一点,但是在使用Image实例调用blur时我得到了undefined method 'map' for #<Context::Image:0x000000012eb020>。如何迭代每个连续的转换,以便模糊返回最新版本的最大n次转换?

class Image
  attr_accessor :array

  def initialize(array)
    self.array = array
  end

  def output_image
    self.array.each do |item|
      puts item.join
    end
  end

  def transform #changes adjacent a 1's adjacent 0's into 1
    cloned = self.array.map(&:clone)

    #scan original array for 1; map crosses into clone if found
    self.array.each.with_index do |row, row_index|
      row.each.with_index do |cell, col|
        if cell == 1
          cloned[row_index][col+1] = 1 unless col+1 >= row.length #copy right
          cloned[row_index+1][col] = 1 unless row_index+1 >= cloned.length # copy down
          cloned[row_index][col-1] = 1 unless col.zero? # copy left
          cloned[row_index-1][col] = 1 unless row_index.zero? #copy up
        end
      end
    end
    cloned
  end

  def blur(n) #should call transform iteratively n times
    blurred = Image.new(self)
    n.times do
      blurred = blurred.transform
    end
    blurred
  end

end

2 个答案:

答案 0 :(得分:1)

mapArray可用的方法,但不适用于您的自定义类Image

我建议您在实例变量map上调用@array。然后,在完成转换后,使用该转换后的数组创建一个新的Image实例。

以下是应该有效的代码示例。请注意,transform和blur将输入数组作为参数,因此它们不依赖于任何实例状态。因此,我已经使它们成为类方法而不是实例方法。这允许用户在不必创建实例的情况下使用它们,如果他们想要做的就是数组转换。它还使这些方法在将来的重构中很容易提取到模块中。我添加了一个实例方法blurred_image,它将转换应用于实例并返回一个新的Image实例。

def self.transform(input_array) #changes adjacent a 1's adjacent 0's into 1
    cloned = input_array.map(&:clone)

    #scan original array for 1; map crosses into clone if found
    input_array.each.with_index do |row, row_index|
      row.each.with_index do |cell, col|
        if cell == 1
          cloned[row_index][col+1] = 1 unless col+1 >= row.length #copy right
          cloned[row_index+1][col] = 1 unless row_index+1 >= cloned.length # copy down
          cloned[row_index][col-1] = 1 unless col.zero? # copy left
          cloned[row_index-1][col] = 1 unless row_index.zero? #copy up
        end
      end
    end
    cloned
  end

  def self.blur(input_array, transform_count) #should call transform iteratively n times
    blurred = input_array
    transform_count.times { blurred = transform(blurred) }
    Image.new(blurred)
  end

  def blurred_image(transform_count)
    self.class.new(self.class.blur(array, transform_count))
  end

答案 1 :(得分:1)

您可以使用Matrix类。

require 'matrix'    

class Matrix
  def el(r,c)
    if r < 0 || r >= row_count || c < 0 || c >= column_count
      0
    else
      self[r,c]
    end
  end

  def transform
    Matrix.build(row_count, column_count) { |r,c|
      [el(r,c), el(r-1,c), el(r+1,c), el(r,c-1), el(r,c+1)].max }
  end
end

给定行 - 列对r, c,如果行或列超出矩阵的边界,则辅助方法el返回0,否则返回值[r,c]。 / p>

nrows = 5
ncols = 5

m = Matrix.build(nrows, ncols) { |r,c| (r==nrows/2 && c==ncols/2) ? 1 : 0 }
  #=> Matrix[[0, 0, 0, 0, 0],
  #          [0, 0, 0, 0, 0],
  #          [0, 0, 1, 0, 0],
  #          [0, 0, 0, 0, 0],
  #          [0, 0, 0, 0, 0]] 
m = m.transform
  #=> Matrix[[0, 0, 0, 0, 0],
  #          [0, 0, 1, 0, 0],
  #          [0, 1, 1, 1, 0],
  #          [0, 0, 1, 0, 0],
  #          [0, 0, 0, 0, 0]] 
m = m.transform
  #   Matrix[[0, 0, 1, 0, 0],
  #          [0, 1, 1, 1, 0],
  #          [1, 1, 1, 1, 1],
  #          [0, 1, 1, 1, 0],
  #          [0, 0, 1, 0, 0]]
m.to_a
  #=>       [[0, 0, 1, 0, 0],
  #          [0, 1, 1, 1, 0],
  #          [1, 1, 1, 1, 1],
  #          [0, 1, 1, 1, 0],
  #          [0, 0, 1, 0, 0]]