Reputation: 117
Given the following code:
cons = [
{ "FirstName" => "Bill",
"LastName" => "Wingy",
"Phone1" => "(800) 552-3209",
"Phone2" => "828 283-1134"
},
{ "FirstName" => "Ted",
"LastName" => "Dimble",
"Phone1" => "(823) 813-2834",
"Phone2" => "8823 232-2342"
}
]
pait_nums = [ "8282831134", "8282831132344" ]
How do you search the cons
array to return the hash where either "Phone1".gsub(/\D/, '')
or "Phone2".gsub(/\D/, '')
matches any string within the pait_nums
array?
Upvotes: 2
Views: 49
Reputation: 110675
phones = ["Phone1", "Phone2"]
cons.find { |h| (h.values_at(*phones).map { |s| s.gsub(/\D/,"") } & pait_nums).any? }
#=> {"FirstName"=>"Bill",
# "LastName"=>"Wingy",
# "Phone1"=>"(800) 552-3209",
# "Phone2"=>"828 283-1134"}
The steps:
find
initially passes the first value of cons
to the block and sets the block variable h
to that value:
h = { "FirstName" => "Bill",
"LastName" => "Wingy",
"Phone1" => "(800) 552-3209",
"Phone2" => "828 283-1134" }
The following block calculations are then performed:
a = h.values_at(*phones)
#=> ["(800) 552-3209", "828 283-1134"]
b = a.map { |s| s.gsub(/\D/,"") }
#=> ["8005523209", "8282831134"]
c = b & pait_nums
#=> ["8005523209", "8282831134"] & ["8282831134", "8282831132344"]
#=> ["8282831134"]
c.any?
#=> true
As c
is true
, find
returns h
. Were c
false
, the second hash would be sent to the block.
Upvotes: 2
Reputation: 6707
Let try this:
cons.select{ |con| pait_nums.include?(con['Phone1'].gsub(/\D/, '')) || pait_nums.include?(con['Phone2'].gsub(/\D/, '')) }
Or make it shorter
phone_keys = %w( Phone1 Phone2 )
cons.select{ |con| con.slice(*phone_keys).values.any?{ |val| pait_nums.include?(val.gsub(/\D/, '')) } }
Upvotes: 0
Reputation: 121000
cons.select do |c|
c.select do |k, _|
k =~ /\APhone\d\z/ # select Phone* keys
end.values # get values
.any? do |p|
pait_nums.include? p.gsub(/\D/, '') # get only matches
end
end
or, for any arbitrary set of keys to check:
keys = %w|Phone1 Phone2|
cons.select do |c|
c.select do |k, _|
keys.include? k # select Phone* keys
end.values.any? do |p|
pait_nums.include? p.gsub(/\D/, '') # get only matches
end
end
Upvotes: 0
Reputation: 1940
If you are using rails then you can use present
in ruby you can use any?
cons.select{ |con| ([con['Phone1'].gsub(/\D/, ''), con['Phone2'].gsub(/\D/, '')] & pait_nums).present?}
In ruby you can use any?
as
cons.select{ |con| ([con['Phone1'].gsub(/\D/, ''), con['Phone2'].gsub(/\D/, '')] & pait_nums).any?}
Upvotes: 0