是否存在从散列中删除键值对的非破坏性方法?
例如,如果你做了
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
被更改,这不是我想要的。
是否有一种方法可以满足我的需求?
答案 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
,尽管当然对于哈希来说它没什么区别。