根据模式从哈希中删除元素

时间:2015-03-21 02:04:43

标签: ruby hash

我有一个看起来像这样的哈希:

{ "cell_number" => 1234567,  "lead source" => [ "referrel", "web", "ad" ], "lead source_selected" => "web" }

现在,如果存在一个模式,其中键包含" x_selected",那么我想返回整个哈希值,x键除外。所以在这种情况下,我希望返回所有内容,而不是"主要来源":

{ "cell_number" : 1234567,  "lead source_selected" : "web" }

我的尝试似乎有效:

 h = { "cell_number" => 1234567,  "lead source" => [ "referrel", "web", "ad" ], "lead source_selected" => "web" }
 h.collect do |k,v|
  if k =~ /(.+)_selected$/
    h.delete( $1 )
  end
 end
 => [nil, nil, ["referrel", "web", "ad"]] 
 > h
 => {"cell_number"=>1234567, "lead source_selected"=>"web"} 

但是有更多的红宝石方法吗?

2 个答案:

答案 0 :(得分:1)

我认为Hash的reject方法会做你想要的。 这是一个例子,然后是输出(我可能错误地模式,但你可以看到它在这里是如何工作的):

myhash = { "cell_number" => 1234567,  "lead source" => [ "referrel", "web", "ad" ], "lead source_selected" => "web" }
puts 'the original hash'
p myhash

puts 'the element rejected by key (exact match)'
p myhash.reject{|k, v| k == 'lead source'}

puts 'same result using regular expression'
p myhash.reject{|k, v| k =~ /^lead source$/}

puts 'the hash is unaffected...'
p myhash

puts '... unless reject! is used instead of reject ...'
myhash.reject!{|k, v| k =~ /^lead source$/}
p myhash

这是输出

the original hash
{"cell_number"=>1234567, "lead source"=>["referrel", "web", "ad"], "lead source_selected"=>"web"}
the element rejected by key (exact match)
{"cell_number"=>1234567, "lead source_selected"=>"web"}
same result using regular expression
{"cell_number"=>1234567, "lead source_selected"=>"web"}
the hash is unaffected...
{"cell_number"=>1234567, "lead source"=>["referrel", "web", "ad"], "lead source_selected"=>"web"}
... unless reject! is used instead of reject ...
{"cell_number"=>1234567, "lead source_selected"=>"web"}

编辑:添加对评论的回复:

啊,我看到...变量可以通过正则表达式中的插值来使用。 它们可以包含部分或全部表达式。例如:

phrase="lead source"
p myhash.reject{|k, v| k =~ /^#{phrase}$/}

pattern="^lead source$"
p myhash.reject{|k, v| k =~ /#{pattern}/}

希望我理解并且这有点帮助。

答案 1 :(得分:1)

一个简单的解决方案:

h = { "cell_number" => 1234567,
      "lead source" => [ "referrel", "web", "ad" ],
      "lead source_selected" => "web" }

bad_keys = h.each_with_object([]) do |(k,_),a|
  prefix = k[/(.+)(?=_selected$)/]
  a << prefix if prefix
end
  #=> ["lead source"]
h.reject { |k,_| bad_keys.include?(k) }
  #=> {"cell_number"=>1234567, "lead source_selected"=>"web"} 

请注意,这使用Hash#reject(不是Enumerable#reject)。正则表达式(?=_selected$)是一个积极的前瞻。 h未发生变异。