散列删除除特定键之外的所有键

除了给定的密钥之外,我希望从散列中删除每个密钥。

例如:

{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address":
{
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021"
},
"phoneNumber":
[
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
]
}

我想删除除“ firstName”和/或“ address”之外的所有内容。

47065 次浏览

Hash#select does what you want:

   h = { "a" => 100, "b" => 200, "c" => 300 }
h.select {|k,v| k > "a"}  #=> {"b" => 200, "c" => 300}
h.select {|k,v| v < 200}  #=> {"a" => 100}

Edit (for comment):

assuming h is your hash above:

h.select {|k,v| k == "age" || k == "address" }

Some other options:

h.select {|k,v| ["age", "address"].include?(k) }

Or you could do this:

class Hash
def select_keys(*args)
select {|k,v| args.include?(k) }
end
end

So you can now just say:

h.select_keys("age", "address")

What about slice?

hash.slice('firstName', 'lastName')
# => { 'firstName' => 'John', 'lastName' => 'Smith' }

Available in Ruby since 2.5

Inspired by Jake Dempsey's answer, this one should be faster for large hashes, as it only peaks explicit keys rather than iterating through the whole hash:

class Hash
def select_keys(*args)
filtered_hash = {}
args.each do |arg|
filtered_hash[arg] = self[arg] if self.has_key?(arg)
end
return filtered_hash
end
end

If you use Rails, please consider ActiveSupport except() method: http://apidock.com/rails/Hash/except

hash = { a: true, b: false, c: nil}
hash.except!(:c) # => { a: true, b: false}
hash # => { a: true, b: false }

No Rails needed to get a very concise code:

keys = [ "firstName" , "address" ]
# keys = hash.keys - (hash.keys - keys) # uncomment if needed to preserve hash order
keys.zip(hash.values_at *keys).to_h
hash = { a: true, b: false, c: nil }
hash.extract!(:c) # => { c: nil }
hash # => { a: true, b: false }