Ruby - тест для массива - PullRequest
       28

Ruby - тест для массива

248 голосов
/ 07 октября 2009

Какой правильный путь:

is_array("something") # => false         (or 1)

is_array(["something", "else"]) # => true  (or > 1)

или узнать количество предметов в нем?

Ответы [ 7 ]

488 голосов
/ 07 октября 2009

Вы, вероятно, хотите использовать kind_of?().

>> s = "something"
=> "something"
>> s.kind_of?(Array)
=> false
>> s = ["something", "else"]
=> ["something", "else"]
>> s.kind_of?(Array)
=> true
143 голосов
/ 07 октября 2009

Вы уверены, что нужно , чтобы быть массивом? Возможно, вы сможете использовать respond_to?(method), чтобы ваш код работал для похожих вещей, которые не обязательно являются массивами (возможно, для некоторых других перечисляемых вещей) Если вам на самом деле нужен array, то лучше всего подходит публикация, описывающая метод Array#kind\_of?.

['hello'].respond_to?('each')
54 голосов
/ 07 октября 2009

Вместо проверки на Array, просто конвертируйте все, что вы получаете, в одноуровневый Array,, чтобы ваш код обрабатывал только один случай.

t = [*something]     # or...
t = Array(something) # or...
def f *x
    ...
end

В Ruby есть различные способы гармонизации API, который может принимать объект или массив объектов, поэтому, догадываясь, почему вы хотите знать, является ли что-то массивом, у меня есть предложение.

Оператор splat содержит много магии , которую вы можете посмотреть, или вы можете просто позвонить Array(something), который добавит оболочку Array, если необходимо. Это похоже на [*something] в этом одном случае.

def f x
  p Array(x).inspect
  p [*x].inspect
end
f 1         # => "[1]"
f [1]       # => "[1]"
f [1,2]     # => "[1, 2]"

Или вы можете использовать splat в объявлении параметра, а затем .flatten, что даст вам другой тип сборщика. (В этом отношении, Вы могли бы также назвать .flatten выше.)

def f *x
  p x.flatten.inspect
end         # => nil
f 1         # => "[1]"
f 1,2       # => "[1, 2]"
f [1]       # => "[1]"
f [1,2]     # => "[1, 2]"
f [1,2],3,4 # => "[1, 2, 3, 4]"

И, спасибо gregschlom , иногда просто быстрее использовать Array(x), потому что когда это уже Array, ему не нужно создавать новый объект.

17 голосов
/ 15 марта 2016

[1,2,3].is_a? Array оценивается как истинное.

12 голосов
/ 07 октября 2009

Звучит так, будто вы ищете что-то, что имеет некоторое представление о предметах. Поэтому я бы порекомендовал посмотреть, если это Enumerable. Это также гарантирует существование #count.

Например,

[1,2,3].is_a? Enumerable
[1,2,3].count

обратите внимание, что, хотя size, length и count все работают для массивов, count является правильным значением здесь (например, 'abc'.length и 'abc'.size оба работают, но 'abc'.count не работает так).

Внимание: строка is_a? Enumerable, так что, возможно, это не то, что вам нужно ... зависит от вашей концепции массива, подобного объекту.

8 голосов
/ 07 октября 2009

Попробуйте:

def is_array(a)
    a.class == Array
end

РЕДАКТИРОВАТЬ : Другой ответ гораздо лучше, чем мой.

5 голосов
/ 12 июля 2017

Также рассмотрите возможность использования Array(). Из Ruby Community Style Guide :

Используйте Array () вместо явной проверки Array или [* var], когда имеете дело с переменной, которую вы хотите рассматривать как массив, но вы не уверены это массив.

# bad
paths = [paths] unless paths.is_a? Array
paths.each { |path| do_something(path) }

# bad (always creates a new Array instance)
[*paths].each { |path| do_something(path) }

# good (and a bit more readable)
Array(paths).each { |path| do_something(path) }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...