【问题标题】:Find and replace in a Ruby multi dimensional array在 Ruby 多维数组中查找和替换
【发布时间】:2011-05-20 22:20:25
【问题描述】:

是否有一种优雅的方法可以在多维数组中查找和替换任何优于 3 的整数(例如)?该数组的维度可能为 1、2、3 或更多。只是这样一个数组的一个例子:

[ [ [ 3, 3, 5 ], 
    [ 4, 3, 3 ] ], 
  [ [ 3, 2, 3 ], 
    [ 0, 3, 8 ] ] ]

我想这样做而不使数组变平。

【问题讨论】:

  • 使用数字 3(因为它是示例中所需的最大值)。

标签: ruby arrays multidimensional-array


【解决方案1】:

按照 sepp2k 的想法,这是一个可能的实现:

class Object
  def deep_map(&block)
    if self.respond_to? :each
      result = []
      self.each do |e|
        result << e.deep_map(&block)
      end
      return result
    else
      return block.call(self)
    end
  end  
end

然后根据需要在数组上应用 deep_map:

> [[[3, 3, 5], [4, 3, 3]], [[3, 2, 3], [0, 3, 8]]].deep_map { |e| e > 3 ? 0 : e }
=> [[[3, 3, 0], [0, 3, 3]], [[3, 2, 3], [0, 3, 0]]] 

或者,更简单地说:

class Object
  def deep_map(&block)
    respond_to?(:map) ? map{|e| e.deep_map(&block)} : block.call(self)
  end
end

或者,多态:

class Object
  def deep_map(&block); block.call(self) end
end

class Array
  def deep_map(&block); map{|e| e.deep_map(&block)} end
end

【讨论】:

  • @i-blis,如果你想要的话,我已经添加了你所写内容的更短版本。
  • each 在较短版本中的map 应该被删除。
  • 你也可以多态地做,正如我添加的那样。
  • 谢谢sawa。较短的版本更具可读性。多态解决方案非常优雅。我在 Ruby 代码中不经常看到这种情况——这是一种流行的编码习惯吗?
  • 我会说不,多态解决方案在 Ruby 中并不常见。在 Ruby 中,使用鸭式打字更为常见。换句话说,一个对象可能会响应map,但不是Array,在这种情况下,“简短”版本可以工作,但多态版本不行。
【解决方案2】:

您可以编写一个deep_map 方法,该方法在数组上调用map,然后为每个元素测试它是否是子数组。如果是,则使用子数组递归调用deep_map,否则产生元素。

然后,您可以使用 deep_map 方法来转换多维数组的内部元素,而不会影响其结构。

【讨论】:

    【解决方案3】:

    所以,如果我做对了,f(x) 将遍历一个多维数组,直到找到一个包含不是 Array 或 Array子类的东西的数组>,此时它将为块产生最里面的数组,并将其替换为块的返回值。

    def f x, &block
      x.map do |a|
        if a.first.class.ancestors.include? Array
          f a, &block
        else
          yield a
        end
      end
    end
    
    p(f [ [ [ 3, 3, 5 ],
            [ 4, 3, 3 ] ],
          [ [ 3, 2, 3 ],
            [ 0, 3, 8 ] ] ] do |e|
        e.reject { |x| x > 3 }
      end
    )
    

    【讨论】:

    • 谢谢你,@DigitalRoss。你的代码很干净。但是,因为我的问题不是很清楚,所以我想保留数组结构。无论如何,再次感谢!
    猜你喜欢
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 2014-12-17
    • 1970-01-01
    • 2018-08-18
    • 1970-01-01
    • 1970-01-01
    • 2019-08-02
    相关资源
    最近更新 更多