从散列中删除密钥的非破坏性方法

时间:2012-11-21 02:53:28

标签: ruby hash side-effects

是否存在从散列中删除键值对的非破坏性方法?

例如,如果你做了

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被更改,这不是我想要的。

是否有一种方法可以满足我的需求?

5 个答案:

答案 0 :(得分:12)

是的,您需要reject

new_hash = original_hash.reject{|key, _| key == :foo}

答案 1 :(得分:8)

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} 

答案 2 :(得分:1)

问题是new_hash是一个引用,除非你明确告诉Ruby复制该对象。你使用dup是正确的轨道,我唯一建议的是做

new_hash = original_hash.dup 

因为我认为你更清楚你正在做什么。

答案 3 :(得分:0)

如何链接dup以减少冗长?

new_hash = original_hash.dup.delete_if{|key, _| key == :foo}

答案 4 :(得分:0)

original_hash.clone.tap {|h| h.delete key}

tap可能比宣布一个新变量更少笨重,主要是因为它在同一条线上。

我认为,

clone更明确地是一个扁平副本,而不是dup,尽管当然对于哈希来说它没什么区别。