我希望这个问题有一个非常简单的答案。我可以想办法用无聊的,烦人的循环来做,但我希望有一个更优雅的解决方案。
如果我有以下两个变量:
hash = {:a => 1, :b => 2, :c => 3, :d => 4}
keyset = [:a, :c]
如何以最简单的方式获得以下两个哈希值?
hash1 = {:a => 1, :c => 3}
hash2 = {:b => 3, :d => 4}
如果示例没有明确我的目标,实质上,我想要的是#delete
和#delete_if
之间的混合 - #delete
返回已删除的值,而{{1允许我批量删除。我更喜欢批量删除的方法,并返回已删除的值 - 或等效的东西。
谢谢!
答案 0 :(得分:33)
使用Hash#slice
和/或Hash#except
尝试有效支持。爆炸方法也存在:
$ irb
>> require 'active_support/core_ext'
=> true
>> hash = {:a => 1, :b => 2, :c => 3, :d => 4}
=> {:a=>1, :d=>4, :b=>2, :c=>3}
>> keyset = [:a, :c]
=> [:a, :c]
>> remainders = hash.slice!(*keyset)
=> {:d=>4, :b=>2}
>> remainders
=> {:d=>4, :b=>2}
>> hash
=> {:a=>1, :c=>3}
答案 1 :(得分:12)
new_hash = {}
keyset.each {|i| new_hash[i] = hash.delete(i)}
这似乎是为我做的,没有提出额外的要求
答案 2 :(得分:12)
hash = { a: 1, b: 2, c: 3, d: 4 }
keyset = [:a, :c]
left, right = hash.partition {|k,v| keyset.include? k }
这左右为数组阵列;转回哈希:
left = Hash[left]
right = Hash[right]
puts "left=#{left.inspect}"
puts "right=#{right.inspect}"
答案 3 :(得分:2)
使用Rails / Active Support,您可以使用extract!
方法:
hash = {:a => 1, :b => 2, :c => 3, :d => 4}
keyset = [:a, :c]
hash2 = hash.extract! *keyset
>> {:a=>1, :c=>3}
hash
>> {:b=>2, :d=>4}
答案 4 :(得分:0)
如果你不介意外部依赖,你可以使用https://github.com/renra/split-off-ruby然后你可以这样做:
hash2 = hash.split_off!(:b, :d)
hash仍将包含键的原始值:a和:c。上述方法已经足够好了,但有时候用正确的方法名称表达你的意图更好,我相信。