Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter an array of hashes to keep only those elements whose hashes contain a key contained in an array?

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}]
like image 693
stevec Avatar asked Oct 28 '25 08:10

stevec


2 Answers

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) }}
like image 174
user11350468 Avatar answered Oct 30 '25 23:10

user11350468


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

like image 45
Timur Shtatland Avatar answered Oct 30 '25 22:10

Timur Shtatland



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!