我正在尋找一種簡單的方法來複制/減少散列,但只包含鍵/數組中指定的鍵/值。如何通過給定的鍵數組來減少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 })
我正在尋找一種簡單的方法來複制/減少散列,但只包含鍵/數組中指定的鍵/值。如何通過給定的鍵數組來減少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 })
你可以嘗試像(以下低效的解決方案)
original_hash.select{|k,v| wanted_keys.include? k }
我並不完全在我的紅寶石富,所以我不知道這是否會返回一個列表或哈希。
,如果你不想要遍歷整個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
如果哈希有一個非常大的數字鍵和/或所需要的鍵的排列是非常大的(不可能爲可能是),由於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_keys
與original_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))]
後兩者應該是首選,因爲它們是最快的。就像你說的那樣,使用'select'和'include'將會隨着散列大小或所需的鍵陣列的增長而減慢處理速度。 –
@theTinMan,感謝您指出,「...或所需的鍵陣列,成長」。我補充說。 –
如果你碰巧使用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
它返回一個哈希值。 –
當作者聲明它可能對或不對時,答案有什麼用?在發佈答案之前做你的研究! '{} .method(:select).owner#=> Hash'告訴你方法是'Hash#select'。說你的代碼工作,因爲'select'返回一個散列,並給出鏈接到文檔:[Hash#select](http://ruby-doc.org/core-2.2.0/Hash.html#method-i-選擇)。我建議你編輯。 –