【问题标题】:iterate with a method within ruby class使用 ruby​​ 类中的方法进行迭代
【发布时间】:2016-08-27 21:06:37
【问题描述】:

类 Image 使用 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 的实例调用模糊时,我得到了 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

【问题讨论】:

    标签: ruby algorithm class iteration


    【解决方案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] 处的值。

    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]] 
    

    【讨论】:

      【解决方案2】:

      map 是一个可用于 Array 的方法,但不适用于您的自定义类 Image

      我建议在您的实例变量@array 上调用map。然后,当您的转换完成后,使用该转换后的数组创建一个新的 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-09
        • 2015-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多