people.select {|person|
person.any? {|k, v|
%w[location hometown].include?(k) && /New York/ =~ v['name']
}}
這基本上是這樣說的:選擇數組中的以下條件爲真的所有條目。條件是:對於任何鍵值對,密鑰是'hometown'
還是'location'
,屬於該密鑰的值的name
屬性是否與正則表達式匹配/New York/
?
但是,您的對象模型似乎嚴重需要重構。事實上,主要的問題是你的對象模型甚至不是一個對象模型,它是一個散列和數組模型。
這裏就是我的意思是通過適當的對象模型:因爲不是戲弄分開的嵌套迷宮bults的堅果
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]
如果你有這樣一個合適的對象模型,你的代碼變得乾淨多了,哈希和數組,你有可愛的小物件,你可以簡單地問幾個問題:
people.select {|person| person.cities.any? {|city| city =~ /New York/ }}
你幾乎可以讀這就像英語:從陣列中選擇其中任何他們的城市的正則表達式匹配/New York/
所有的人。
如果我們改善了對象模型進一步,它會變得更好:
class Person
def lived_in?(pattern)
cities.any? {|city| city =~ pattern }
end
end
people.select {|person| person.lived_in?(/New York/) }
這基本上說,「從人民中,選擇在同一時間住在紐約的那些」。這比「從人們選擇所有關鍵值對的第一個元素是字符串'hometown'
或字符串'location'
,並且鍵值對的第二個元素匹配正則表達式/New York/
」要好得多。
這已更新 – kylemac 2010-07-27 15:01:42