如何通过给定的键数组减少Ruby哈希?

时间:2016-07-13 14:59:13

标签: ruby

我正在寻找一种复制/减少哈希的简单方法,但只包括在键数组中指定的键/值。

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 })

5 个答案:

答案 0 :(得分:4)

如果散列具有非常多的键和/或所需键的数组非常大(可能不太可能),

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_keysoriginal_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))]

答案 1 :(得分:3)

这是为了您的规格传递:)

original_hash.slice(*wanted_keys)

答案 2 :(得分:2)

如果你不想迭代整个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

答案 3 :(得分:1)

如果您正好使用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 Support核心扩展代码rails/activesupport/lib/active_support/core_ext/hash/slice.rb

答案 4 :(得分:0)

您可以尝试类似(下面的低效解决方案)

original_hash.select{|k,v| wanted_keys.include? k }

我并不完全依赖我的Ruby-foo,所以我不确定这是否会返回列表或哈希。