2016-07-13 53 views
0

我正在尋找一種簡單的方法來複制/減少散列,但只包含鍵/數組中指定的鍵/值。如何通過給定的鍵數組來減少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 }) 

回答

0

你可以嘗試像(以下低效的解決方案)

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

我並不完全在我的紅寶石富,所以我不知道這是否會返回一個列表或哈希。

+1

它返回一個哈希值。 –

+4

當作者聲明它可能對或不對時,答案有什麼用?在發佈答案之前做你的研究! '{} .method(:select).owner#=> Hash'告訴你方法是'Hash#select'。說你的代碼工作,因爲'select'返回一個散列,並給出鏈接到文檔:[Hash#select](http://ruby-doc.org/core-2.2.0/Hash.html#method-i-選擇)。我建議你編輯。 –

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 
4

如果哈希有一個非常大的數字鍵和/或所需要的鍵的排列是非常大的(不可能爲可能是),由於wanted_keys線性搜索需要對每個original_hash的鍵

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

將是相對低效的。以下是加快速度的兩種方法。 (@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 2.0版,當Array#to_h首次亮相,這將被寫入

Hash[wanted_keys.zip(original_hash.values_at(*wanted_keys))] 
+0

後兩者應該是首選,因爲它們是最快的。就像你說的那樣,使用'select'和'include'將會隨着散列大小或所需的鍵陣列的增長而減慢處理速度。 –

+0

@theTinMan,感謝您指出,「...或所需的鍵陣列,成長」。我補充說。 –

0

如果你碰巧使用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方法是目前在積極支持核心擴展代碼rails/activesupport/lib/active_support/core_ext/hash/slice.rb

相關問題