Сравните несколько значений в массиве Ruby - PullRequest
1 голос
/ 27 июля 2010
[
    {
        "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 ]

4 голосов
/ 27 июля 2010
people.select {|person|
  person.any? {|k, v|
    %w[location hometown].include?(k) && /New York/ =~ v['name']
}}

В основном это говорит о следующем: выберите все записи в массиве, для которых выполняется следующее условие. Условие: верно ли для любой из пар ключ-значение, что ключ является либо 'hometown', либо 'location', а свойство name значения, принадлежащего этому ключу, соответствует Regexp /New York/?

Однако ваша объектная модель, похоже, серьезно нуждается в рефакторинге. На самом деле главная проблема в том, что ваша объектная модель - это даже не объектная модель, это модель хешей и массивов.

Вот что я имею в виду под правильной объектной моделью:

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]

Если у вас есть такая подходящая объектная модель, ваш код становится намного чище, потому что вместо того, чтобы разбирать гайки на части вложенного лабиринта хешей и массивов, у вас есть красивые маленькие объекты, которые вы можете просто задать несколько вопросов: 1013 *

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', а второй элемент пары« ключ-значение »совпадает с Regexp /New York/».

1 голос
/ 27 июля 2010

Я думаю, что в решении Йерга есть небольшая ошибка - «местоположение» и «родной город» не используются, поэтому, например, следующий «человек» пройдет тест:

{
  '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']
}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...