2010-07-27 60 views
1
[ 
    { 
     "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的,我怎么会能够循环并拔出所有的“故乡”和“位置”键,看看哪些人有新的价值纽约吗?比较多个值在Ruby阵列

我的问题是我可以Array.each通过这些项目,但我不知道如何遍历我的标准(“纽约”)的两个位置& &家乡。

+0

这已更新 – kylemac 2010-07-27 15:01:42

回答

4
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/”要好得多。

+0

我已经更新了JSON是有效的,你介意再给它看看吗? – kylemac 2010-07-27 15:01:13

+0

@ kylemac:它的工作原理。 – 2010-07-27 15:03:40

+0

你介意解释这里发生了什么?我是ruby的新手,这有点超过我的脑海 – kylemac 2010-07-27 15:13:49

1

我觉得约尔格的解决方案有一个小问题 - “位置”和“家乡”都没有用,因此,举例来说,下面的“人”将通过测试:

{ 
    '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'] 
}} 
+0

+1,谢谢你的注意。主要是我的脑部疾病。我*确实记得要从芝加哥加入一个人到测试集,以便我可以确定过滤器是否正在工作*,但我完全错过了*特定的角落案例。干得不错! (哦,对于IDE来说,如果我已经将这些代码输入到我个人最喜欢的NetBeans中,而不是愚蠢的StackOverflow WYSIWIG编辑器和IRB,它会立即将这两个代码强调为“未使用的局部变量”。) – 2010-07-27 22:49:48