[
{
"name": "John Doe",
"location": {
"name": "New York, New York",
"id": 12746342329
},
"hometown": {
"name": "Brooklyn, New York",
"id": 43453644
}
},
{
"name": "Jane Doe",
"location": {
"name": "Miami, Florida",
"id": 12746342329
},
"hometown": {
"name": "Queens, New York",
"id": 12746329
}
}
]
鉴于这段JSON,我如何能够循环并取出所有“家乡”和“位置”键,看看哪些人具有纽约的价值?
我的问题是我可以通过这些项目来实现Array.each,但我不知道如何遍历这两个位置&&我的标准(“纽约”)的故乡。
答案 0 :(得分:4)
people.select {|person|
person.any? {|k, v|
%w[location hometown].include?(k) && /New York/ =~ v['name']
}}
这基本上说明如下:选择数组中满足以下条件的所有条目。条件是:对于任何键值对,如果键为'hometown'
或'location'
并且属于该键的值的name
属性与Regexp {匹配},则为真{1}}?
但是,您的对象模型似乎非常需要重构。实际上,主要问题是你的对象模型甚至不是对象模型,它是一个哈希和数组模型。
这就是我所说的适当对象模型:
/New York/
如果你有这样一个合适的对象模型,你的代码会变得更加清晰,因为你可以简单地提出一些问题,而不是将哈希和数组的嵌套迷宫的结果分开。 / p>
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'
以及键值对的第二个元素与Regexp {匹配”的要好得多{1}}”。
答案 1 :(得分:1)
我认为Jörg的解决方案有一个小错误 - “位置”和“家乡”没有使用,所以,例如,跟随“人”将通过测试:
{
'name' => 'Foo Bar',
'favourite movie' => {
name => 'New York, New York!'
}
}
以下是纠正它的一个镜头,以及评论:
ary.select {|person| # get me every person satisfying following condition
%w[location hometown].any? {|key| # check if for any of the strings 'location' and 'hometown'
# person should have that key, and its 'name' should contain /New York/ regexp
person[key] && person[key]['name'] && /New York/ =~ person[key]['name']
}}