Delete array of keys in Ruby Hash
19,276
Solution 1
You can iterate over an array of keys and delete everyone of them:
[key1, key2, key3].each { |k| some_hash.delete k }
Can't remember any better solution.
Solution 2
This is exactly what you are looking for... You can do it like this without looping through the array unnecessarily.
keys_to_delete = [key1, key2, key3]
hash_array.except!(*keys_to_delete)
The result is stored in hash_array
Solution 3
You can try to use Hash#delete_if:
delete_if deletes every key-value pair from hsh for which block evaluates to true.
array_hash.delete_if { |key, _| [key1, key2, key3].include? key }
UPDATE
If you don't want to iterate over array of keys, you can use Set instead of Array
(since Set
uses Hash
as storage include?
is O(1)):
require 'set'
keys = [key1,key2,key3].to_set
array_hash.delete_if { |key, _| keys.include? key }
Solution 4
Maybe it's worth to make a method
class Hash
def delete_by_keys *keys
keys.each{|k| delete(k)}
end
end
hash_array.delete_by_keys(key1,key2,..)
Author by
Artem Kalinchuk
Updated on June 17, 2022Comments
-
Artem Kalinchuk about 2 years
How would I go about deleting an array of keys in a hash? For example, you can call:
hash.delete(some_key)
But how can I do this:
hash.delete([key1,key2,key3,...])
without needing to looping manually.
-
Artem Kalinchuk over 12 yearsI'm trying to stay away from loops because they're slow and this code is time sensitive.
-
KL-7 over 12 yearsI see, but if you deal with an array of keys you have to iterate over it anyway. What are the sizes of hash and array in your case?
-
Artem Kalinchuk over 12 yearsI don't really need to iterate through the array of keys, just need to delete those keys in the hash. The hash has about 20,000 items but it has to loop multiple times with items being different each time.
-
KL-7 over 12 yearsI meant that any method that you would use to delete values from the hash by keys from the array will need to iterate over that array (it'll at least look through each key). That means computational time is at least linear of the length of the array (multiplied by complexity of deleting by key from hash). Though, I might be wrong and would be happy to see a better solution.
-
undur_gongor over 12 years+1. I was just going to add this. Of course, it iterates through the items too (even several times).
-
KL-7 over 12 yearsIf size of the hash is way bigger than size of the array this approach is less efficient than iterating over an array.
-
Aliaksei Kliuchnikau over 12 years@KL-7, agree, it is always required to do penformance benchmarks before optimizing some code, optimization without measurement may increase execution time and memory consumption. I would not bother to optimize code like this. OP just has several alternatives :)
-
steenslag over 12 years@Artem Kalinchuk A hash does not loop to find a key, it is way faster than that. Here's how hash is implemented in Ruby:.
-
Artem Kalinchuk over 12 years@steenslag what's your solution?
delete_if
loops.[key1, key2, key3].each {|k| some_hash.delete k }
loops too. -
steenslag over 12 yearsYou loop the array once; you search the hash (which is fast) multiple times. I tried it; created a hash with 20_000 random 5 letter words and an array with 10_000 5 letter words. The line by @KL-7 took 0.02 seconds to execute (and this computer is old).
-
steenslag over 12 yearsIn other words, i think this is a fine solution.
-
Artem Kalinchuk over 12 yearsGotcha. I ended up using this solution, it works as expected and executes pretty fast.
-
kuboon about 11 years
keys.map
instead ofkeys.each
returns deleted values array. useful. -
sokkyoku almost 8 yearsThis is part of rails, not ruby.