Ruby:有没有更有效的方法将哈希键子集转换为下划线符号?



我希望从这个

{'productId' => '1234', 'unwantedKey' => 'nope'}

{:product_id => '1234'}

假设在本例中我只需要productId键/值。在下面的代码中,api_key返回一个我想从散列中提取的键数组。有没有更好的方法?

product.delete_if { |k, v| !api_keys.include? k }.inject({}){|memo,(k,v)| memo[k.underscore.to_sym] = v; memo}

您可以过滤api_keys,然后使用each_with_object来构建您的哈希片:

slice = api_keys.find_all { |k| h.has_key?(k) }.each_with_object({ }) { |k,o| o[k.underscore.to_sym] = h[k] }

each_with_object通常是比inject更好的选择,如果你是迭代而不是减少。

给定

:

h        = { 'productId' => '1234', 'unwantedKey' => 'nope' }
api_keys = [ 'productId' ]

以上收益:

slice = { :product_id => '1234' }

find_all/each_with_object还具有由api_keys(即您想要的键)显式驱动的附加优势,这可能(也可能不)对您和维护您的代码的人很重要。

一个简单的解决方案是同时做每一个并添加另一个哈希:

result  = {}
product = {'productId' => '1234', 'unwantedKey' => 'nope'}
product.each do |key,value|
  if api_keys.include?(k)
    result[key.underscore.to_sym] = value
  end
end
api_keys = ['productId'] # etc...
product = {'productId' => '1234', 'unwantedKey' => 'nope'}
result = product.inject({}) do |hash, (key, value)|
  hash[key.underscore.to_sym] = value if api_keys.include?(key); hash
end

您可以考虑的一件事是是否要避免delete传递。

final = {}
initial.each do |k, v|
  final[k.underscore.sym] = v if api_keys.include?(k)
end

final = initial.inject({}) do |h, (k,v)|
  h[k.underscore.sym] = v if api_keys.include?(k)
  h
end 

这个问题很老了,但是既然我偶然发现了它,其他人可能也会这样。这是我的看法,假设activessupport核心扩展加载,因为你正在使用String#underscore:

hash = {'productId' => '1234', 'unwantedKey' => 'nope'}
api_keys = ['productId']
filtered = hash.slice(*api_keys).each.with_object({}) do |(k,v),h|
  h[k.underscore.to_sym] = v
end

最新更新