8

是否有从哈希中删除键值对的非破坏性方法?

例如,如果你做了

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)

thenoriginal_hash没有改变,new_hash也改变了,但它们有点冗长。但是,如果你这样做了

original_hash = {:foo => :bar}
new_hash = original_hash
new_hash.delete(:foo)

然后original_hash改变了,这不是我想要的。

有没有一种方法可以满足我的要求?

4

5 回答 5

14

是的,你想要reject

new_hash = original_hash.reject{|key, _| key == :foo}
于 2012-11-21T03:08:04.893 回答
9

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} 
于 2012-11-21T03:09:39.363 回答
1

问题是 new_hash 是一个引用,除非您明确告诉 Ruby 复制该对象。您使用 dup 走在正确的轨道上,我唯一推荐的就是这样做

new_hash = original_hash.dup 

因为我认为你在做什么更明确。

于 2012-11-21T03:02:11.097 回答
0

如何链接 dup 以使其不那么冗长?

new_hash = original_hash.dup.delete_if{|key, _| key == :foo}
于 2012-11-21T03:03:42.793 回答
0
original_hash.clone.tap {|h| h.delete key}

tap可以说没有声明一个新变量那么笨重,主要是因为它在同一行。

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

于 2017-03-09T05:20:24.817 回答