ハッシュに新しいペアを追加するには、次のようにします。
{:a => 1, :b => 2}.merge!({:c => 3}) #=> {:a => 1, :b => 2, :c => 3}
ハッシュからキーを削除するための同様の方法はありますか?
これは動作します:
{:a => 1, :b => 2}.reject! { |k| k == :a } #=> {:b => 2}
しかし、私は以下のようなものがあると期待するでしょう
{:a => 1, :b => 2}.delete!(:a) #=> {:b => 2}
戻り値が残りのハッシュ値になることが重要です。そのため、次のようにします。
foo(my_hash.reject! { |k| k == my_key })
一行で。
Railsにはexcept/exceptがあります。 method これらのキーを削除してハッシュを返します。すでにRailsを使っているのであれば、これを自分で作成しても意味がありません。
class Hash
# Returns a hash that includes everything but the given keys.
# hash = { a: true, b: false, c: nil}
# hash.except(:c) # => { a: true, b: false}
# hash # => { a: true, b: false, c: nil}
#
# This is useful for limiting a set of parameters to everything but a few known toggles:
# @person.update(params[:person].except(:admin))
def except(*keys)
dup.except!(*keys)
end
# Replaces the hash without the given keys.
# hash = { a: true, b: false, c: nil}
# hash.except!(:c) # => { a: true, b: false}
# hash # => { a: true, b: false }
def except!(*keys)
keys.each { |key| delete(key) }
self
end
end
OnelinerプレーンなRuby、それはRuby> 1.9.xでのみ動作します。
1.9.3p0 :002 > h = {:a => 1, :b => 2}
=> {:a=>1, :b=>2}
1.9.3p0 :003 > h.tap { |hs| hs.delete(:a) }
=> {:b=>2}
Tap methodは常に呼び出されたオブジェクトを返します...
そうでなければactive_support/core_ext/hash
(全てのRailsアプリケーションで自動的に必要とされる)を必要とするなら、あなたはあなたの必要性に応じて以下の方法のうちの一つを使うことができます。
➜ ~ irb
1.9.3p125 :001 > require 'active_support/core_ext/hash' => true
1.9.3p125 :002 > h = {:a => 1, :b => 2, :c => 3}
=> {:a=>1, :b=>2, :c=>3}
1.9.3p125 :003 > h.except(:a)
=> {:b=>2, :c=>3}
1.9.3p125 :004 > h.slice(:a)
=> {:a=>1}
except はブラックリストアプローチを使用するので、argsとしてリストされているすべてのキーを削除します。一方、 slice はホワイトリストアプローチを使用します。したがって、引数としてリストされていないキーはすべて削除します。与えられたハッシュを変更するが、それらの戻り値が異なっているそれらの両方がハッシュを返すそれらのメソッド(except!
とslice!
)の強打バージョンも存在します。これはslice!
用に削除されたキーとexcept!
用に保持されているキーを表します。
1.9.3p125 :011 > {:a => 1, :b => 2, :c => 3}.except!(:a)
=> {:b=>2, :c=>3}
1.9.3p125 :012 > {:a => 1, :b => 2, :c => 3}.slice!(:a)
=> {:b=>2, :c=>3}
単に使用しないでください:
hash.delete(key)
ハッシュからキーを削除し、Rubyで残りのハッシュを取得する方法はたくさんあります。
.slice
=>選択したキーを返し、元のハッシュから削除しません
2.2.2 :074 > hash = {"one"=>1, "two"=>2, "three"=>3}
=> {"one"=>1, "two"=>2, "three"=>3}
2.2.2 :075 > hash.slice("one","two")
=> {"one"=>1, "two"=>2}
2.2.2 :076 > hash
=> {"one"=>1, "two"=>2, "three"=>3}
.delete
=>元のハッシュから選択されたキーを削除します(それは一つのキーだけを受け入れ、一つを超えない)
2.2.2 :094 > hash = {"one"=>1, "two"=>2, "three"=>3}
=> {"one"=>1, "two"=>2, "three"=>3}
2.2.2 :095 > hash.delete("one")
=> 1
2.2.2 :096 > hash
=> {"two"=>2, "three"=>3}
.except
=>残りのキーを返しますが、元のハッシュから何も削除しません
2.2.2 :097 > hash = {"one"=>1, "two"=>2, "three"=>3}
=> {"one"=>1, "two"=>2, "three"=>3}
2.2.2 :098 > hash.except("one","two")
=> {"three"=>3}
2.2.2 :099 > hash
=> {"one"=>1, "two"=>2, "three"=>3}
.delete_if
=>値に基づいてキーを削除する必要がある場合。元のハッシュから一致するキーを明らかに削除します
2.2.2 :115 > hash = {"one"=>1, "two"=>2, "three"=>3, "one_again"=>1}
=> {"one"=>1, "two"=>2, "three"=>3, "one_again"=>1}
2.2.2 :116 > value = 1
=> 1
2.2.2 :117 > hash.delete_if { |k,v| v == value }
=> {"two"=>2, "three"=>3}
2.2.2 :118 > hash
=> {"two"=>2, "three"=>3}
Ruby 2.2.2に基づく結果。
純粋なRuby(Railsなし)を使いたいのであれば、拡張メソッドを作成したくない(多分これは1つか2つの場所でしか必要とせず、たくさんのメソッドで名前空間を汚染したくないでしょう)。ハッシュをその場で編集する(つまり、私のような関数型プログラミングのファンであれば)、 'select':
>> x = {:a => 1, :b => 2, :c => 3}
=> {:a=>1, :b=>2, :c=>3}
>> x.select{|x| x != :a}
=> {:b=>2, :c=>3}
>> x.select{|x| ![:a, :b].include?(x)}
=> {:c=>3}
>> x
=> {:a=>1, :b=>2, :c=>3}
#in lib/core_extensions.rb
class Hash
#pass single or array of keys, which will be removed, returning the remaining hash
def remove!(*keys)
keys.each{|key| self.delete(key) }
self
end
#non-destructive version
def remove(*keys)
self.dup.remove!(*keys)
end
end
#in config/initializers/app_environment.rb (or anywhere in config/initializers)
require 'core_extensions'
削除しながら、.removeがハッシュを削除したキーのコピーを返すように設定しました。ハッシュ自体を変更します。これはRubyの規約に沿っています。例:コンソールから
>> hash = {:a => 1, :b => 2}
=> {:b=>2, :a=>1}
>> hash.remove(:a)
=> {:b=>2}
>> hash
=> {:b=>2, :a=>1}
>> hash.remove!(:a)
=> {:b=>2}
>> hash
=> {:b=>2}
>> hash.remove!(:a, :b)
=> {}
facets
gemからexcept!
を使用できます。
>> require 'facets' # or require 'facets/hash/except'
=> true
>> {:a => 1, :b => 2}.except(:a)
=> {:b=>2}
元のハッシュは変わりません。
編集:Russelが言っているように、ファセットにはいくつかの隠れた問題があり、ActiveSupportと完全にAPI互換ではありません。一方、ActiveSupportはファセットほど完成度が高くありません。最後に、私はASを使用し、あなたのコードにEdgeのケースを入れておくことにしました。
モンキーパッチを適用するか、不必要に大きなライブラリを含める代わりに、 Ruby 2を使用している場合は改良 を使用できます。
module HashExtensions
refine Hash do
def except!(*candidates)
candidates.each { |candidate| delete(candidate) }
self
end
def except(*candidates)
dup.remove!(candidates)
end
end
end
プログラムの他の部分に影響を与えたり、大きな外部ライブラリを含めなくても、この機能を使用できます。
class FabulousCode
using HashExtensions
def incredible_stuff
delightful_hash.except(:not_fabulous_key)
end
end
純粋なRubyでは:
{:a => 1, :b => 2}.tap{|x| x.delete(:a)} # => {:b=>2}
を参照してください。Ruby on Rails:複数のハッシュキーを削除する
hash.delete_if{ |k,| keys_to_delete.include? k }
Deleteがハッシュの削除ペアを返す場合、それは素晴らしかったです。私はこれをやっている:
hash = {a: 1, b: 2, c: 3}
{b: hash.delete(:b)} # => {:b=>2}
hash # => {:a=>1, :c=>3}
これは1行の方法ですが、あまり読みやすくありません。代わりに2行を使用することをお勧めします。
use_remaining_hash_for_something(Proc.new { hash.delete(:key); hash }.call)
ハッシュキーを削除する複数の方法あなたは下から任意の方法を使用することができます
hash = {a: 1, b: 2, c: 3}
hash.except!(:a) # Will remove *a* and return HASH
hash # Output :- {b: 2, c: 3}
hash = {a: 1, b: 2, c: 3}
hash.delete(:a) # will remove *a* and return 1 if *a* not present than return nil
たくさんの方法がありますので、RubyのHash/doc here を見てください。
ありがとうございました