[英]How to reduce a Ruby hash by a given array of keys?
我正在寻找一种简单的方法来复制/减少散列,但只包含在键数组中指定的键/值。
original_hash = { one: 1, two: 'too', three: 3 }
wanted_keys = [:one, :three]
new_hash = # do something with the hash
expect(new_hash).to eq({ one: 1, three: 3 })
如果散列有非常多的键和/或想要的键的数组非常大(可能不太可能),
original_hash.select { |k, v| wanted_keys.include?(k) }
由于线性搜索将是相对低效wanted_keys
需要为每个original_hash
的密钥。 这里有两种方法可以加快速度。 (@Lucas 的解决方案是第三种方式。)
将wanted_keys
转换为一个集合
require 'set'
wanted_keys_set = wanted_keys.to_set
original_hash.select { |k, v| wanted_keys_set.include?(k) }
#=> {:one=>1, :three=>3}
将wanted_keys
与original_hash
中这些键的值匹配,然后将结果数组转换为哈希
wanted_keys.zip(original_hash.values_at(*wanted_keys)).to_h
#=> {:one=>1, :three=>3}
在Ruby v2.0之前, Array#to_h
刚出道的时候,会这样写
Hash[wanted_keys.zip(original_hash.values_at(*wanted_keys))]
这是为了你的规范通过:)
original_hash.slice(*wanted_keys)
如果你碰巧使用 Rails,你可以使用Hash#slice
require "active_support/core_ext/hash"
original_hash = { one: 1, two: 'too', three: 3 }
wanted_keys = [:one, :three]
new_hash = original_hash.slice *wanted_keys
#=> {:one=>1, :three=>3}
Hash#slice
方法的实现存在于 Active 支持核心扩展代码rails/activesupport/lib/active_support/core_ext/hash/slice.rb
如果你不想迭代整个Hash
,你可以使用each_with_object
original_hash = {one: 1, two: 'too', three: 3}
wanted_keys = [:one, :three]
# iterate only array of keys
new_hash = wanted_keys.each_with_object({}) do |key, exp|
exp[key] = original_hash[key] if original_hash[key]
end
您可以尝试类似(下面的低效解决方案)
original_hash.select{|k,v| wanted_keys.include? k }
我并不完全依赖我的 Ruby-foo,所以我不确定这是否返回列表或哈希。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.