Эндрю: Я вызываю API, и в JSON я получаю ответ, если есть несколько результатов, я получаю массив, но если есть только один, я получаю хэш, а не один элемент массива. Есть ли лучший способ вперед, чем проверка Array vs Hash?
drhyde
2
Так вы получаете [result_hash, another_result_hash]или single_result_hash? Кто бы ни создал этот API, он не справлялся с работой!
Эндрю Гримм
2
Вы правы, Эндрю, и держу пари, что гораздо проще заставить людей, написавших API, исправить это, чем проверять хеш против массива.
Оливье Ольбаум Шерлер
У меня такая же ситуация, как у @drhyde. В моем случае третьей стороной является HTTParty, который после анализа XML-файла не может решить, как лучше всего справиться с ситуацией, когда элемент может иметь 1-n дочерних элементов.
Стоит отметить, что "is_a?" Метод true, если класс находится где угодно в дереве предков объектов. например:
@some_var.is_a?(Object)# => true
вышеупомянутое верно, если @some_var является экземпляром хеша или другого класса, который происходит от Object. Итак, если вы хотите строгое соответствие для типа класса, используя == или instance_of? Метод, вероятно, то, что вы ищете.
is_a?это лучший вариант, так как он также возвращает trueдля подклассов.
Фабио Батиста
И, конечно, вы также не учитываете скобки, так что @som_var.is_a? Hashтоже работает :)
Гас Шортц
7
Будьте осторожны, это может действительно вас испортить, если кто-то в конечном итоге передаст вам экземпляр ActiveSupport :: HashWithIndifferentAccess. Который отвечает как хеш, но на самом деле не является хешем. :(
открывает
Мне также хотелось бы, чтобы больше подробностей касалось типизации утки, поскольку первоначальный автор явно искал рубиновый способ проверки типов.
NobodysNightmare
3
@unflores ActiveSupport::HashWithIndifferentAccessнаследуется от Hash, поэтому @some_var.is_a?(Hash)в этом случае также вернет true. (У меня был тот же вопрос и случай HashWithIndifferentAccess, и я немного запутался в вашем комментарии ... поэтому я хотел уточнить)
Stilzk1n
38
Прежде всего, лучший ответ на буквальный вопрос
Hash===@some_var
Но на этот вопрос действительно нужно было ответить, показывая, как здесь можно печатать на уток. Это немного зависит от того, какая утка вам нужна.
@some_var.respond_to?(:each_pair)
или
@some_var.respond_to?(:has_key?)
или даже
@some_var.respond_to?(:to_hash)
может быть правильным в зависимости от приложения.
Обычно в ruby, когда вы ищете «type», вы на самом деле хотите «duck-type» или «действительно ли это кряк, как утка?». Вы увидите, отвечает ли он определенному методу:
@some_var.respond_to?(:each)
Вы можете перебрать @some_var, потому что он отвечает на: каждый
Если вы действительно хотите знать тип, и если это Hash или Array, то вы можете сделать:
["Hash","Array"].include?(@some_var.class)#=> check both through instance class@some_var.kind_of?(Hash)#=> to check each at once@some_var.is_a?(Array)#=> same as kind_of
Это не сработает, если ваш код зависит от порядка данных (например, если вы используете each_with_index). Порядок элементов реализуются по- разному между хэш и массивами , и она отличается от версии Ruby (. Intertwingly.net/slides/2008/oscon/ruby19/22 )
juan2raid
1
@ juan2raid: Если порядок важен, то sortсначала позвоните по нему.
Эндрю Гримм
@ Второй пример Брэндона должен преобразовать класс в строку. <br/>["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
На практике вам часто хочется действовать по-разному, в зависимости от того, является ли переменная массивом или хешем, а не просто сказать. В этой ситуации элегантная идиома заключается в следующем:
case itemwhenArray#do somethingwhenHash#do something elseend
Обратите внимание, что вы не вызываете .classметод item.
Обратите внимание, что это не работает для подклассов ! Например, если у вас есть ActiveRecord::Collectionи попробуйте, instance_of?(Array)то это вернется false, тогда как is_a?(Array)вернется true.
Том Лорд
0
Если вы хотите проверить, является ли объект строго или расширяется Hash, используйте:
value ={}
value.is_a?(Hash)|| value.is_a?(Array)#=> true
Но чтобы оценить утку Руби, вы можете сделать что-то вроде:
value ={}
value.respond_to?(:[])#=> true
Это полезно, когда вы хотите получить доступ только к некоторому значению с использованием value[:key]синтаксиса.
Обратите внимание, что Array.new["key"]поднимет TypeError.
[result_hash, another_result_hash]
илиsingle_result_hash
? Кто бы ни создал этот API, он не справлялся с работой!Ответы:
Вы можете просто сделать:
или также что-то вроде:
Стоит отметить, что "is_a?" Метод true, если класс находится где угодно в дереве предков объектов. например:
вышеупомянутое верно, если @some_var является экземпляром хеша или другого класса, который происходит от Object. Итак, если вы хотите строгое соответствие для типа класса, используя == или instance_of? Метод, вероятно, то, что вы ищете.
источник
is_a?
это лучший вариант, так как он также возвращаетtrue
для подклассов.@som_var.is_a? Hash
тоже работает :)ActiveSupport::HashWithIndifferentAccess
наследуется от Hash, поэтому@some_var.is_a?(Hash)
в этом случае также вернет true. (У меня был тот же вопрос и случай HashWithIndifferentAccess, и я немного запутался в вашем комментарии ... поэтому я хотел уточнить)Прежде всего, лучший ответ на буквальный вопрос
Но на этот вопрос действительно нужно было ответить, показывая, как здесь можно печатать на уток. Это немного зависит от того, какая утка вам нужна.
или
или даже
может быть правильным в зависимости от приложения.
источник
Обычно в ruby, когда вы ищете «type», вы на самом деле хотите «duck-type» или «действительно ли это кряк, как утка?». Вы увидите, отвечает ли он определенному методу:
Вы можете перебрать @some_var, потому что он отвечает на: каждый
Если вы действительно хотите знать тип, и если это Hash или Array, то вы можете сделать:
источник
sort
сначала позвоните по нему.["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
это также можно использовать с оператором case
источник
Я использую это:
Это работает для Hash и ActiveSupport :: HashWithIndifferentAccess.
источник
На практике вам часто хочется действовать по-разному, в зависимости от того, является ли переменная массивом или хешем, а не просто сказать. В этой ситуации элегантная идиома заключается в следующем:
Обратите внимание, что вы не вызываете
.class
методitem
.источник
Ты можешь использовать
instance_of?
например
источник
ActiveRecord::Collection
и попробуйте,instance_of?(Array)
то это вернетсяfalse
, тогда какis_a?(Array)
вернетсяtrue
.Если вы хотите проверить, является ли объект строго или расширяется
Hash
, используйте:Но чтобы оценить утку Руби, вы можете сделать что-то вроде:
Это полезно, когда вы хотите получить доступ только к некоторому значению с использованием
value[:key]
синтаксиса.источник
источник