如何替换所有具有'。'?的哈希键。

时间:2013-11-27 19:43:12

标签: ruby hash

我正在使用Ruby on Rails 4,我想替换所有哈希键,以便更改哈希

h_before = {:"aaa.bbb" => 1, :c => 2, ...}

h_after = {:bbb => 1, :c => 2, ...}

也就是说,我想在某种程度上“解压缩”具有.的所有散列键。我该怎么做?

6 个答案:

答案 0 :(得分:3)

h_before = {:"aaa.bbb" => 1, :c => 2}
h_after =
h_before.inject({}){|h, (k, v)| h[k.to_s.split(".").last.to_sym] = v; h}
# => {:bbb = > 1, :c => 2}

答案 1 :(得分:3)

each_with_object比从答案中注入更简洁,更简洁:

h_before.each_with_object({}){|(k, v),h| h[k.to_s.split(".").last.to_sym] = v}
=> {:bbb=>1, :c=>2}

答案 2 :(得分:2)

由于有许多答案声称要做同样的事情,我认为是时候发布一些基准:

require 'fruity'

h_before = {:"aaa.bbb" => 1, :c => 2}

def cdub_test(hash)
  Hash[hash.map {|k, v| [k.to_s.gsub(/^.*\./,"").to_sym, v]}]
end

def matt_test(old_hash)
  Hash[old_hash.map { |k,v| [ k.to_s.sub(/.*\./,'').to_sym, v ] }]
end

class Hash
  require 'active_support/core_ext/hash/indifferent_access'
  def grep_keys(pattern)
    return inject(HashWithIndifferentAccess.new){|h, (k, v)|
      h[$1 || k] = v  if pattern =~ k.to_s ;  h }
  end
end

def phlip_test(hash)
  hash.grep_keys(/\.(\w+)$/)
end

def bjhaid_test(hash)
  hash.each_with_object({}){|(k, v),h| h[k.to_s.split(".").last.to_sym] = v}
end

def sawa_test(hash)
  hash.inject({}){|h, (k, v)| h[k.to_s.split(".").last.to_sym] = v; h}
end

compare do
    cdub   { cdub_test(h_before)   }
    matt   { matt_test(h_before)   }
    phlip  { phlip_test(h_before)  }
    bjhaid { bjhaid_test(h_before) }
    sawa   { sawa_test(h_before)   }
end

哪个输出:

Running each test 1024 times. Test will take about 1 second.
bjhaid is similar to sawa
sawa is faster than matt by 60.00000000000001% ± 10.0%
matt is faster than phlip by 30.000000000000004% ± 10.0% (results differ: {:bbb=>1, :c=>2} vs {"bbb"=>1})
phlip is similar to cdub (results differ: {"bbb"=>1} vs {:bbb=>1, :c=>2})

请注意,phlip的代码不会返回所需的结果。

答案 3 :(得分:1)

old_hash = {:"aaa.bbb" => 1, :c => 2 }
new_hash = Hash[old_hash.map { |k,v| [ k.to_s.sub(/.*\./,'').to_sym, v ] }]

答案 4 :(得分:0)

1.9.3p448 :001 > hash = {:"aaa.bbb" => 1, :c => 2 }
 => {:"aaa.bbb"=>1, :c=>2} 

1.9.3p448 :002 > Hash[hash.map {|k, v| [k.to_s.gsub(/^.*\./,"").to_sym, v]}]
 => {:bbb=>1, :c=>2} 

答案 5 :(得分:0)

我的grep_keys在这里从来没有让我失望过:

class Hash
  def grep_keys(pattern)
    return inject(HashWithIndifferentAccess.new){|h, (k, v)| 
      h[$1 || k] = v  if pattern =~ k.to_s ;  h }
  end
end

它返回哈希的浅表副本,但只返回匹配的键。如果输入正则表达式包含()匹配,则该方法将使用匹配的值替换该键。 (注意,这可能会合并两个或多个键,并丢弃除了它们之外的所有键!)我一直使用它来将Rails param切割成仅包含某些模块所需键的子参数。

{:"aaa.bbb" => 1, :c => 2 }.grep_keys(/\.(\w+)$/)返回{"bbb"=>1}

此方法会将您的实际问题升级为“如何定义符合您的意思的正则表达式”。“”。“