比较Ruby数组中的多个值

时间:2010-07-27 14:28:46

标签: ruby arrays json

[
    {
        "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,但我不知道如何遍历这两个位置&&我的标准(“纽约”)的故乡。

2 个答案:

答案 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']
}}