我有一个用例,我有一个现有的哈希:
response = { aa: 'aaa', bb: 'bbb' }
我需要添加id
作为键之一。
当我使用 response.merge(id: 'some_id')
然后将其转换为 JSON 时,我id
作为最后一个元素,这是我不想要的。
我想在response
开头插入id: 'some_id'
.我已经尝试过这个,但迭代它感觉不太好:
new_response = { id: 'some id' }
response.keys.reverse.each {|key| new_response[key] = response[key] }
基本上,我需要类似的功能,例如Ruby Array的unshift
。
irb(main):042:0> arr = [1, 2, 3]
=> [1, 2, 3]
irb(main):043:0> arr.unshift(5)
=> [5, 1, 2, 3]
response = {aa: 'aaa', bb: 'bbb'}
new_response = {new: 'new_value'}.merge(response)
# => {:new=>"new_value", :aa=>"aaa", :bb=>"bbb"}
尝试将其转换为数组并返回:
Hash[hash.to_a.unshift([k, v])]
你可以这样做:
response.inject({:new=>"new_value"}) { |h,(k,v)| h[k]=v; h }
或喜欢@sawa
这对我来说很有用,因为我希望"timestamp"在 json 的前 128 个字符内,以便 Splunk 读取它,所以我想重新排序哈希键以确保时间戳在转换to_json
时始终位于开头。由于日志行会经常打印,我想确保最快的速度,检查不同的组合:
使用以下代码来确定哪种解决方案最快:
require 'securerandom'
require 'active_support/core_ext/hash/reverse_merge'
require 'fruity'
SMALL_HASH = { aa: 'aaa', bb: 'bbb' }.freeze
BIG_HASH = 10_000.times.each_with_object({}) do |_, obj|
obj[SecureRandom.alphanumeric(6).to_sym] = SecureRandom.alphanumeric(128)
end; nil
puts "Running on #{RUBY_VERSION}"
# Running on 2.6.9
compare do
_small_merge { { new: 'new_value' }.merge(SMALL_HASH) }
_small_reverse_merge { SMALL_HASH.reverse_merge(new: 'new_value') }
_small_unshift { Hash[SMALL_HASH.to_a.unshift([:new, 'new_value'])] }
end
# Running each test 32768 times. Test will take about 1 second.
# _small_merge is faster than _small_reverse_merge by 19.999999999999996% ± 10.0%
# _small_reverse_merge is faster than _small_unshift by 1.9x ± 0.1
compare(magnify: 1_000) do
_big_merge { { new: 'new_value' }.merge(BIG_HASH) }
_big_reverse_merge { BIG_HASH.reverse_merge(new: 'new_value') }
_big_unshift { Hash[BIG_HASH.to_a.unshift([:new, 'new_value'])] }
end
# Running each test 1000 times.
# _big_reverse_merge is similar to _big_merge
# _big_merge is faster than _big_unshift by 2x ± 0.1
所以我建议使用以下策略
{ new: 'new_value' }.merge(aa: 'aaa', bb: 'bbb')