Reputation: 52258
Here we have an array of hashes. How can we keep only the hashes for which at least one key is contained in an array?
# array of hashes
@arr_of_h = [{first: 10},
{second: 10, secondB: 10},
{third: 10, thirdB: 10}]
# array
arr = ["first", "third"]
Desired output
@output = [{:first=>10}, {:third=>10, :thirdB=>10}]
Upvotes: 4
Views: 2839
Reputation: 1407
Try the below with Array select:
select
will return an array containing elements which match the condition provided on the block.
Hope the hash on every index of the array will include only one key
@arr_of_h.select{ |element| arr.include?(element.keys.first.to_s) }
EDIT #1
To find the record which at least has one key contained in an array
We can achieve it through Array select and Array any?
@arr_of_h.select{ |element| element.keys.any? {|element| arr.include?(element.to_s) }}
Upvotes: 4
Reputation: 1959
This would work if you have hashes in your array with more than one key and you wanted to keep hashes if one of the hash keys was present the 'keep' array.
arr_of_h.delete_if { |hash| (arr & (hash.keys.map(&:to_s))).empty? }
As Cary rightfully pointed out, this does mutate the array. If you do not wish to mutate the array:
arr_of_h.select { |hash| (arr & (hash.keys.map(&:to_s))).any? }
Upvotes: 2
Reputation: 12347
If speed is important, and if the array has many elements, which translates to many lookups, use a set
. Also, for speed, convert the array to symbols at the beginning, rather than converting it in the select
loop. Note that for the particular case described by the OP, the speed improvements would be tiny if any, since all inputs are small.
require "Set"
@arr_of_h = [{first: 10}, {second: 10}, {third: 10}]
arr = ["first", "third"]
arr_as_set = arr.map(&:to_sym).to_set
@output = @arr_of_h.select { |h| arr_as_set.include?(h.keys.first) }
puts @output
# Prints:
# {:first=>10}
# {:third=>10}
SEE ALSO:
Set#include?
docs
Set#include?
vs. Array#include?
More on Set#include?
Speed comparisons for arrays, sets, and hashes, with benchmarks
Upvotes: 2