有没有一种非破坏性的方法可以从哈希中删除键值对?
例如,如果您这样做了
original_hash = {:foo => :bar}
new_hash = original_hash
new_hash = new_hash.reject{|key, _| key == :foo}
或
original_hash = {:foo => :bar}
new_hash = original_hash
new_hash = new_hash.dup
new_hash.delete(:foo)
然后original_hash
没有改变,new_hash
改变了,但它们有点冗长。但是,如果您这样做了
original_hash = {:foo => :bar}
new_hash = original_hash
new_hash.delete(:foo)
然后original_hash
被改变,这不是我想要的。
有没有一种方法可以做我想做的?
是的,你想要reject
:
new_hash = original_hash.reject{|key, _| key == :foo}
ActiveSupport 提供了一个哈希扩展:Hash#except。它允许您返回除指定键之外的新哈希,而无需修改原始哈希。
假设您已经安装了active_support gem:
ruby-1.9.3> require 'active_support/core_ext/hash/except.rb'
=> true
ruby-1.9.3> a = {x: 2, y: 1, z: 3}
=> {:x=>2, :y=>1, :z=>3}
ruby-1.9.3> b = a.except(:x)
=> {:y=>1, :z=>3}
ruby-1.9.3> c = a.except(:x, :y)
=> {:z=>3}
ruby-1.9.3> a
=> {:x=>2, :y=>1, :z=>3}
ruby-1.9.3> b
=> {:y=>1, :z=>3}
ruby-1.9.3> c
=> {:z=>3}
问题是new_hash是一个引用,除非你明确告诉Ruby复制对象。 使用 dup 你走在正确的轨道上,我唯一可能建议做的就是做
new_hash = original_hash.dup
因为我认为这对你在做什么更明确。
如何链接 dup 以使其不那么冗长?
new_hash = original_hash.dup.delete_if{|key, _| key == :foo}
original_hash.clone.tap {|h| h.delete key}
tap
可以说没有声明一个新变量那么笨拙,主要是因为它在同一行上。
我认为,clone
比dup
更明确地是一个平面副本,尽管当然对于哈希来说它几乎没有区别。