как проверить, что все атрибуты / значения в классе или объекте json равны нулю - PullRequest
0 голосов
/ 16 мая 2018

У меня есть метод, который извлекает запрос эластичного поиска из API и преобразует его в массив объектов JSON.

В некоторых случаях последний объект JSON не является нулевым объектом, но все атрибуты имеют нулевые значения.

Я бы хотел избежать отображения для каждого объекта, но мне нужно отфильтровать те объекты JSON, которые имеют все нулевые значения.

например:

=> [#<Api::User:0x006546546
      @user_id=1,
      @height=70,
      @age=25>,
    #<Api::User:0x006546542
      @user_id=nil
      @height=nil
      @age=nil>]

Я хочу удалить объект «все ноль» из массива либо в формате JSON, либо после преобразования в массив объектов Api :: User.

Является ли карта единственным способом проверки всех значений всех объектов или существует менее ресурсоемкий метод?

Ответы [ 4 ]

0 голосов
/ 17 мая 2018

Я бы налегал на методы, которые Enumerable и Object дают вам.Из Enumerable мы можем использовать select для выбора только тех элементов массива, которые удовлетворяют некоторому условию.Это условие состоит в том, что по крайней мере одна из переменных экземпляра не является nil, и для этого мы можем использовать any?.

С Object мы будем использовать instance_variables, чтобы получить коллекцию переменных экземпляраи мы получим доступ к значению этих переменных экземпляра с помощью instance_variable_get.

Это будет выглядеть примерно так:

filtered_array = array.select do |object| 
  object.instance_variables.any? { |var| object.instance_variable_get(var) }
end

Конечно, any? эффективен в том, что он остановитсяитерации и верните true в самой первой «истинной» переменной.По предложению SteveTurczyn, если вам нужно только проверить последнее значение, это еще быстрее.

filtered_array = array[0..-2] if array[-1].instance_variables.none? { |var| object.instance_variable_get(var) }
0 голосов
/ 16 мая 2018

Я уверен, что есть более чистый способ, но на всякий случай вам нужно отобразить каждый объект:

def are_attributes_not_nil?(my_object)
  my_object.instance_variables.map{ |attr| my_object.send(attr.to_s[1..-1]).nil? }.uniq.include? false
end

возвращает false, если все атрибуты равны nil

0 голосов
/ 16 мая 2018

Мое решение заключается в том, чтобы сначала реализовать способ преобразования объектов в хэши, а затем превратить их в сам JSON.

api_user_array #=> [#<Api::User:0x006546546 ... >, #<Api::User:0x006546542 ... >]
api_user_array = api_user_array.map(&:to_h).reject { |hash| hash.values.all?(&:nil?) }
# should result in an array of hashes with at least one value not nil

Предполагается, что вы реализуете метод Api :: User # to_h . Это может быть что-то вроде этого:

def attribute_names
  %w[user_id height age]
end

def to_h
  attribute_names.each_with_object({}) { |attr, hash| hash[attr] = send(attr) }
  # assuming all attributes have a getter, otherwise
  attribute_names.each_with_object({}) { |attr, hash| hash[attr] = instance_variable_get("@#{attr}") }
end
0 голосов
/ 16 мая 2018

Кто-то может придумать лучший способ, но, похоже, вам не нужно проверять все значения всех объектов, поскольку первое проверяемое значение, отличное от nil, означает, что объект хорош. Я бы сделал что-то, что проверяет каждое значение до того момента, когда будет найдено ненулевое значение. Это также помогло бы повысить эффективность, если бы вы могли заказать проверенные поля, которые, скорее всего, сначала будут иметь значение (например, user_id)

array.select do |object|
  %i(user_id height age).find do |field_name| 
    object.send(field_name)
  end
end

Если это только последний объект, который нужно проверить, то еще проще ...

array.pop if %i(user_id height age).find {|field_name| array.last.send(field_name) }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...