2012-11-21 12 views
5

Czy istnieje nieniszczący sposób usunięcia pary wartości klucza z hasza?Nieniszczący sposób usuwania klucza z hasza

Na przykład, jeśli nie

original_hash = {:foo => :bar} 
new_hash = original_hash 
new_hash = new_hash.reject{|key, _| key == :foo} 

lub

original_hash = {:foo => :bar} 
new_hash = original_hash 
new_hash = new_hash.dup 
new_hash.delete(:foo) 

następnie original_hash pozostaje niezmieniona, a new_hash ulega zmianie, ale są ciut gadatliwy. Jednakże, jeśli nie

original_hash = {:foo => :bar} 
new_hash = original_hash 
new_hash.delete(:foo) 

następnie original_hash ulega zmianie, co nie jest to, co chcę.

Czy istnieje jedna metoda, która robi to, co chcę?

+2

'original_hash' * jest * zmieniane w twoim pierwszym przykładzie używając' delete_if'. Ponadto, 'new_hash' w twoim drugim przykładzie używającym' delete' pobiera wartość skojarzoną z ': foo', tj.': Bar', a nie sam skrót. –

+0

@shioyama dzięki za to! > _ < –

Odpowiedz

8

ActiveSupport przewiduje rozszerzenie skrótu: Hash#except. Pozwala na zwrócenie nowego skrótu poza określonymi kluczami bez modyfikowania oryginału.

Zakładając zainstalowaniu gem active_support:

ruby-1.9.3> require 'active_support/core_ext/hash/except.rb' 
=> true 
ruby-1.9.3> a = {x: 2, y: 1, z: 3} 
=> {:x=>2, :y=>1, :z=>3} 
ruby-1.9.3> b = a.except(:x) 
=> {:y=>1, :z=>3} 
ruby-1.9.3> c = a.except(:x, :y) 
=> {:z=>3} 
ruby-1.9.3> a 
=> {:x=>2, :y=>1, :z=>3} 
ruby-1.9.3> b 
=> {:y=>1, :z=>3} 
ruby-1.9.3> c 
=> {:z=>3} 
+1

Nie używam ActiveSupport, ale fakt, że dostarczają taką metodę jest dobrym dowodem, że sama Ruby nie ma takiej metody. –

1

Problem polega na tym, że new_hash jest odniesieniem, chyba że wyraźnie powiesz Ruby, aby powielił obiekt. Jesteś na dobrej drodze, za pomocą dup, jedyne co mogę polecić to zrobić

new_hash = original_hash.dup 

bo myślę, to jest to bardziej wyraźne, co robisz.

0

Co powiesz na przynależność do dup, aby było mniej szczegółowe?

new_hash = original_hash.dup.delete_if{|key, _| key == :foo} 
13

Tak, chcesz reject:

new_hash = original_hash.reject{|key, _| key == :foo} 
0
original_hash.clone.tap {|h| h.delete key} 

tap jest zapewne mniej niż niezgrabne deklarowania nowej zmiennej, głównie dlatego, że znajduje się na tej samej linii.

clone jest, jak sądzę, wyraźniej płaska kopia niż dup, chociaż oczywiście dla skrótów nie ma to większego znaczenia.

+0

Chociaż ten fragment kodu może rozwiązać pytanie, [w tym wyjaśnienie] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-ans -answers) naprawdę pomaga poprawić jakość twojego posta. Pamiętaj, że odpowiadasz na pytanie przeznaczone dla czytelników w przyszłości, a te osoby mogą nie znać powodów sugestii dotyczących kodu. – DimaSan

Powiązane problemy