people.select {|person|
person.any? {|k, v|
%w[location hometown].include?(k) && /New York/ =~ v['name']
}}
This basically says the following: select all entries in the array for which the following condition is true. The condition is: is it true for any of the key-value pairs that the key is either 'hometown'
or 'location'
and the name
property of the value belonging to that key matches the Regexp /New York/
?
However, your object model seems to be in a serious need of refactoring. In fact, the main problem is that your object model isn't even an object model, it's a hash and array model.
Here's what I mean by a proper object model:
class Person
attr_reader :name, :location, :hometown
def initialize(name, location=nil, hometown=nil)
@name, @location, @hometown = name, location, hometown
end
def cities
return @location, @hometown
end
end
class City
attr_reader :id, :name
def initialize(id, name)
@id, @name = id, name
end
def =~(other)
name =~ other
end
end
nyc = City.new(12746342329, 'New York, New York')
brooklyn = City.new(43453644, 'Brooklyn, New York')
miami = City.new(12746342329, 'Miami, Florida')
queens = City.new(12746329, 'Queens, New York')
john = Person.new('John Doe', nyc, brooklyn)
jane = Person.new('Jane Doe', miami, queens)
people = [john, jane]
If you have such a proper object model, your code becomes much cleaner, because instead of teasing apart the nuts of bults of a nested maze of hashes and arrays, you have nice little objects that you can simply ask some questions:
people.select {|person| person.cities.any? {|city| city =~ /New York/ }}
You can almost read this like English: from the array select all people for which any of their cities matches the Regexp /New York/
.
If we improve the object model further, it gets even better:
class Person
def lived_in?(pattern)
cities.any? {|city| city =~ pattern }
end
end
people.select {|person| person.lived_in?(/New York/) }
This basically says "From the people, select the ones which at one time lived in New York". That's much better than "from the people select all for which the first element of the key value pair is either the string 'hometown'
or the string 'location'
and the second element of the key value pair matches the Regexp /New York/
".