Ruby Hash破坏性与非破坏性方法

时间:2014-09-15 18:54:34

标签: ruby hash

无法找到回答我问题的上一篇文章...我正在学习如何在Ruby中使用破坏性和非破坏性方法。我找到了我正在进行的练习的答案(破坏性地为哈希值添加了一个数字),但我想清楚为什么我的一些早期解决方案不起作用。这是有效的答案:

  def modify_a_hash(the_hash, number_to_add_to_each_value)
    the_hash.each { |k, v| the_hash[k] = v + number_to_add_to_each_value}
  end

这两个解决方案以非破坏性的方式回归(因为它们都使用“每个”我无法弄清楚为什么。为了制造具有破坏性的东西,上面的等号可以解决这个问题吗?):

  def modify_a_hash(the_hash, number_to_add_to_each_value)
    the_hash.each_value { |v| v + number_to_add_to_each_value}
  end

  def modify_a_hash(the_hash, number_to_add_to_each_value)
    the_hash.each { |k, v| v + number_to_add_to_each_value}
  end

2 个答案:

答案 0 :(得分:2)

条款"破坏性"和#34;非破坏性的"这里有点误导。更好的是使用传统的"就地修改" vs."返回副本"术语

通常,就地修改的方法在其名称末尾有!作为警告,例如String的gsub!。一些早于此约定的方法没有它们,例如push for Array。

=在循环中执行赋值。您的其他示例实际上并没有做任何有用的事情,因为each会返回正在迭代的原始对象,而不管是否产生任何结果。

如果您想要返回副本,请执行以下操作:

def modify_a_hash(the_hash, number_to_add)
  Hash[
    the_hash.collect do |k, v|
      [ k, v + number_to_add ]
    end
  ]
end

那会返回一份副本。内部操作collect将键值对转换为应用了调整的新键值对。由于没有分配,因此不需要=

外部方法Hash[]将这些键值对转换为适当的Hash对象。然后返回并独立于原始文件。

通常是非破坏性的,或者"返回副本"方法需要创建一个新的独立版本的东西,它为了存储结果而进行操作。这适用于String,Array,Hash或您可能正在使用的任何其他类或容器。

答案 1 :(得分:0)

也许这个略有不同的例子会有所帮助。

我们有一个哈希:

2.0.0-p481 :014 > hash
 => {1=>"ann", 2=>"mary", 3=>"silvia"}

然后我们迭代它并将所有字母更改为大写:

2.0.0-p481 :015 > hash.each { |key, value| value.upcase! }
 => {1=>"ANN", 2=>"MARY", 3=>"SILVIA"}

原始哈希已经改变,因为我们使用了大写!方法

比较没有的方法!符号,不会修改哈希值:

2.0.0-p481 :017 > hash.each { |key, value| value.downcase }
=> {1=>"ANN", 2=>"MARY", 3=>"SILVIA"}