[ruby] Ruby - test for array

What is the right way to:

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

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

or to get the count of items in it?

This question is related to ruby syntax

The answer is


Are you sure it needs to be an array? You may be able to use respond_to?(method) so your code would work for similar things that aren't necessarily arrays (maybe some other enumberable thing). If you do actually need an array, then the post describing the Array#kind\_of? method is best.

['hello'].respond_to?('each')

It sounds like you're after something that has some concept of items. I'd thus recommend seeing if it is Enumerable. That also guarantees the existence of #count.

For example,

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

note that, while size, length and count all work for arrays, count is the right meaning here - (for example, 'abc'.length and 'abc'.size both work, but 'abc'.count doesn't work like that).

Caution: a string is_a? Enumerable, so perhaps this isn't what you want... depends on your concept of an array like object.


Instead of testing for an Array, just convert whatever you get into a one-level Array, so your code only needs to handle the one case.

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

Ruby has various ways to harmonize an API which can take an object or an Array of objects, so, taking a guess at why you want to know if something is an Array, I have a suggestion.

The splat operator contains lots of magic you can look up, or you can just call Array(something) which will add an Array wrapper if needed. It's similar to [*something] in this one case.

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

Or, you could use the splat in the parameter declaration and then .flatten, giving you a different sort of collector. (For that matter, you could call .flatten above, too.)

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]"

And, thanks gregschlom, it's sometimes faster to just use Array(x) because when it's already an Array it doesn't need to create a new object.


[1,2,3].is_a? Array evaluates to true.


Also consider using Array(). From the Ruby Community Style Guide:

Use Array() instead of explicit Array check or [*var], when dealing with a variable you want to treat as an Array, but you're not certain it's an array.

# 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) }

Try:

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

EDIT: The other answer is much better than mine.