如何在Ruby/Rails中从哈希表中删除一个键并获取剩余的哈希表?

679

我要向哈希表添加一个新的键值对,我会这样做:

{:a => 1, :b => 2}.merge!({:c => 3})   #=> {:a => 1, :b => 2, :c => 3}
有没有类似的方法可以从哈希表中删除一个键?
这个代码是可行的:
{:a => 1, :b => 2}.reject! { |k| k == :a }   #=> {:b => 2}

但我希望有类似这样的东西:

{:a => 1, :b => 2}.delete!(:a)   #=> {:b => 2}

重要的是返回值应该是剩余的哈希值,这样我才能执行以下操作:

foo(my_hash.reject! { |k| k == my_key })

一行代码实现。


1
如果你真的需要,你可以随时扩展(在运行时打开)内置的哈希表来添加这个自定义方法。 - dbryson
Ruby 3 将拥有这个功能。https://www.ruby-lang.org/en/news/2020/09/25/ruby-3-0-0-preview1-released/ - B Seven
18个回答

13

对于大型数据集,keys_to_delete.each {|k| hash.delete(k)} 更快。如果我错了,请纠正我。 - Vignesh Jayavel
@VigneshJayavel,你说得对,但是OP想要返回哈希值。each会返回数组。 - Nakilon

5
删除hash表中的键值对如果能返回被删除的键值对将会非常好。 我正在进行以下操作:
hash = {a: 1, b: 2, c: 3}
{b: hash.delete(:b)} # => {:b=>2}
hash  # => {:a=>1, :c=>3} 

我找到了一个简单而优雅的方法来完成这个任务,看看我的答案吧 :) - Narfanator

4
尝试使用“except!”方法。
{:a => 1, :b => 2}.except!(:a)   #=> {:b => 2}

2
使用deleteexceptexcept! sample_hash = {hey: 'hey', hello: 'hello'} 删除:
sample_hash.delete(:hey)
=> 'hey'

sample_hash
=> {hello: 'hello'}

返回键的值并从原始对象中删除该键,如果没有这样的键,则返回nil。
除外:
sample_hash.except(:hey)
=> {hello: 'hello'}

sample_hash
=> {hey: 'hey', hello: 'hello'}

返回整个哈希表中不包含指定键的内容,但不会更新原始哈希表。
除外!: except!与except相同,但它会永久改变原始哈希表的状态,就像所有带有bang操作的方法一样。
sample_hash.except!(:hey)
=> {hello: 'hello'}

sample_hash
=> {hello: 'hello'}

1

删除哈希表中的键有多种方法。您可以使用以下任何一种方法:


hash = {a: 1, b: 2, c: 3}
hash.except!(:a) # Will remove *a* and return HASH
hash # Output :- {b: 2, c: 3}

hash = {a: 1, b: 2, c: 3}
hash.delete(:a) # will remove *a* and return 1 if *a* not present than return nil

有很多方法可以使用,您可以查看Ruby文档中关于哈希的这里

谢谢


1
这是一种一行完成的方法,但不太易读。建议改为使用两行。
use_remaining_hash_for_something(Proc.new { hash.delete(:key); hash }.call)

1
Hash#exceptHash#except!已经被提到了足够多的次数。正如你所提到的,Proc.new版本不是很易读,而且比use_remaining_hash_for_something(begin hash.delete(:key); hash end)更复杂。也许只需删除此答案。 - Michael Kohl
1
我简化了我的回答并删除了已经说过的内容。保留我的回答以及你的评语,因为它们回答了问题并提供了使用的良好建议。 - frediy

0

我想删除一组键,并返回已删除的哈希的“片段”:

Rails:

hash = {a: 1, b: 2, c: 3}

def delete_slice!(hash, *keys)
  hash.slice(*keys).tap { hash.except!(*keys) }
end

delete_slice!(hash, :a, :b)
# => {a: 1, b: 2}
hash
# => {c: 3}

纯粹的Ruby:
hash = {a: 1, b: 2, c: 3}

def delete_slice!(hash, *keys)
  hash.slice(*keys).tap { keys.each{ hash.delete _1 } }
end

delete_slice!(hash, :a, :b)
# => {a: 1, b: 2}
hash
# => {c: 3}

-13
这个也可以: hash[hey] = nil

3
h = {:a => 1, :b => 2, :c => 3}; h[:a]=nil; h.each{|k,v| puts k}这段代码的意思是:创建一个名为h的哈希表,其中键值对为{:a => 1, :b => 2, :c => 3},将h中键为:a的值设为nil,然后遍历哈希表的每一个键并输出。与其不同的代码是: h = {:a => 1, :b => 2, :c => 3}; h.delete(:a); h.each{|k,v| puts k}这段代码的意思是:创建一个名为h的哈希表,其中键值对为{:a => 1, :b => 2, :c => 3},删除哈希表中键为:a的键值对,然后遍历哈希表的每一个键并输出。 - obaqueiro
1
从哈希表中删除一个键并不等同于从哈希表中删除一个键的值。由于这可能会让人们感到困惑,最好是删除这个答案。 - Sebastián Palma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接