2013-06-22 4 views
1

В методе я получаю список параметров, переданных в. Некоторые из них связаны с определенной областью. Я хочу сохранить эти специальные ключи в другом хэше, чтобы передать его другому методу и удалить их из исходного хэша.выберите и удалите из хеша в ruby ​​

(я на самом деле, пишущие рельсы simple_form пользовательский ввод, но это не имеет значения)

Я следующий код:

all_options = { :key1 => 1, :key2 => 2, :something_else => 42 } 

my_keys = [:key1, :key2, :key3, :key4] 
my_options = all_options.select {|k,v| my_keys.include?(k)} 
all_options.delete_if {|k,v| my_keys.include?(k)} 

# expecting 
my_options == { :key1 => 1, :key2 => 2 } 
all_options == { :something_else => 42 } 

Теперь мой вопрос есть лучше, то есть умнее способ сделать это?

Возможно, это просто сахар, но я хочу знать.

+1

Не могли бы вы опубликовать точный вход (ы)/вывод, который вы ожидаете, которые мы можем вставить в наших редакторов попробовать? – Dogbert

+0

все ваше сообщение создает путаницу. Скорее дайте некоторый образец ввода и обработайте ожидаемый результат и на более легких заметках, что вы пробовали .. делает хороший вопрос, я думаю .. –

+0

извините за путаницу. Я думал, что было бы полезно добавить то, что я пробовал, чтобы избежать получения тех же идей. Надеюсь, что сейчас лучше. –

ответ

1
all_options = { :key1 => 1, :key2 => 2, :something_else => 42 } 
my_keys = [:key1, :key2, :key3, :key4] 

my_options = my_keys.inject({}) {|h,k| h[k] = all_options.delete(k) if all_options.key?(k);h} 

all_options 
# => {:something_else=>42} 
my_options 
# => {:key1=>1, :key2=>2} 

вот способ улучшить ответ Ju Лю:

all_options = { :key1 => 1, :key2 => 2, :something_else => 42 } 
my_keys = [:key1, :key2, :key3, :key4] 

my_options = all_options.extract!(*my_keys).keep_if {|k,v| v} 

all_options 
# => {:something_else=>42} 
my_options 
# => {:key1=>1, :key2=>2} 

однако вы потеряете ваши варианты, если какой-либо ключ в all_options хэш имеет фактическое значение из nil или false (не знаю, если вам нужно, чтобы держать их):

all_options = { :key1 => 1, :key2 => nil, :something_else => 42 } 

вот способ держать false «s

my_options = all_options.extract!(*my_keys).keep_if {|k,v| !v.nil?} 

P.S. можно было бы сохранить все значения, включая nil с, если вы храните ключи от all_options:

all_options = { :key1 => 1, :key2 => 2, :something_else => 42 } 
all_keys = all_options.keys 
my_keys = [:key1, :key2, :key3, :key4] 

my_options = all_options.extract!(*my_keys).keep_if {|k,v| all_keys.include?(k)} 

all_options 
# => {:something_else=>42} 
my_options 
# => {:key1=>1, :key2=>2} 
+0

Спасибо за ответ. На первый взгляд, это не более читаемо, чем две строки, которые у меня есть. Похоже, что нет встроенного способа. Тем не менее, я попробую все версии и посмотрю, с чем я счастлив. –

+0

Да, 'Hash' api не имеет собственного метода для непосредственного использования того, что вам нужно. Кроме того, если вы хотите, чтобы код был более читаемым (и особенно если вы его использовали в нескольких местах), вы можете инкапсулировать этот oneliner в методе с читаемым именем ... что-то вроде 'def split_by_my_keys (all_options, my_keys)' или независимо от того, что вы считаете удобным для вас. – trushkevich

+0

Да, конечно. В настоящее время он используется в одном месте. Если мне это нужно чаще, я рассматриваю возможность открытия класса Hash и добавление метода его выполнения.Спасибо –

1

Возможно, способ extract! в active_support может работать?

+0

Это не плохо, но 'my_options = all_options.extract! (: Key1,: key2,: ключ3,: Key4)' также устанавливает ': ключ3 => ноль,: Key4 => nil', которые я не» я хочу. Можем ли мы улучшить это? –

1

Я знаю только Рубин. Так вот мой рубин подход:

all_options = { :key1 => 1, :key2 => 2, :something_else => 42 } 

my_keys = [:key1, :key2, :key3, :key4] 

#below statement is your my_options 

Hash[my_keys.map{|i| [i,all_options.delete(i)] if all_options.has_key? i }.compact] 
# => {:key1=>1, :key2=>2} 

all_options 
# => {:something_else=>42} 
+0

Спасибо за ответ. На первый взгляд, это не более читаемо, чем две строки, которые у меня есть. Похоже, что нет встроенного способа. Тем не менее, я попробую все версии и посмотрю, с чем я счастлив. –