根据模式从散列中删除元素

remove element from hash based on pattern

我有一个看起来像这样的散列:

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

现在,如果有一个模式,其中键包含 "x_selected",那么我想 return 整个散列,x 键除外。所以在这种情况下,我想要 return 除了 "lead source":

之外的所有内容
{ "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(  )
  end
 end
 => [nil, nil, ["referrel", "web", "ad"]] 
 > h
 => {"cell_number"=>1234567, "lead source_selected"=>"web"} 

但是还有更多 ruby 的方法吗?

我认为 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}/}

希望我理解了并且这对您有所帮助。

一个简单的解决方案:

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 (not Enumerable#reject)。 (?=_selected$) 在正则表达式中是一个积极的前瞻。 h没有变异。