从哈希中删除密钥的非破坏性方法



有没有一种非破坏性的方法可以从哈希中删除键值对?

例如,如果您这样做了

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可以说没有声明一个新变量那么笨拙,主要是因为它在同一行上。

我认为,clonedup更明确地是一个平面副本,尽管当然对于哈希来说它几乎没有区别。

最新更新