2015-03-21 2 views
1

У меня есть хэш, который выглядит следующим образом:удалить элемент из хэша на основе шаблона

{ "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"} 

Но есть более рубиновый способ сделать это?

+0

Если есть ключ '' X_selected'', вы хотите удалить «Х» из хэша, правильно? –

+0

@muistooshort yes – Donato

ответ

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 не мутируется.

+0

Я просто добавляю эту ссылку, потому что это помогло мне понять, когда использовать each_with_object и уменьшить (ввести): http://www.bbs-software.com/blog/2013/11/22/rubys-injectreduce-and-each_with_object / – Donato

1

Я думаю, что метод Хэша 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"} 

Edit: добавляет ответ на комментарий:

Ах, я вижу ... переменные могут использоваться интерполяцией в регулярном выражении. Они могут содержать часть или все выражения. Примеры:

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

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

Надеюсь, я понял и это вообще помогает.

+1

В вашем примере вы используете hardcoding 'lead source', но я не знаю фактического имени ключа. Я просто знаю, что ключ x должен быть удален, если хэш также включает x_selected, где x может быть любым словом. – Donato

+0

(удалил этот ответ и добавил его в мой предыдущий ответ для форматирования.) – codess

+0

В дополнение к комментарию @ Donato, центральная точка вопроса заключается в том, чтобы определить, какие пары ключ/значение (если они есть) должны быть удалены, что необходимо сделать в коде, а не визуальным контролем. –

Смежные вопросы