tags:

views:

1675

answers:

5

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?

+10  A: 

You probably want to use kind_of?().

>> s = "something"
=> "something"
>> s.kind_of?(Array)
=> false
>> s = ["something", "else"]
=> ["something", "else"]
>> s.kind_of?(Array)
=> true
ry
I really like this one. +1
tyndall
+2  A: 

Try:

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

EDIT: The other answer is much better than mine.

Lucas Jones
good to know this method too +1
tyndall
+4  A: 

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')
zgchurch
In this case I am sure it will be an Array. But nice to know this method too. +1
tyndall
Interesting idea, I'm using push/pop on a data structure. Would anything besides arrays respond to those methods?
Drew
+2  A: 

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.

Peter
A: 

t = [*thing]

You might want to use the splat operator *. This is used to unwrap arrays, and it is particularly useful when you want to take an array or a single value and know how to write the code to handle it, which might be what you are working on.

In this case, you would add one level of array [] deliberately, but inside you would use *thing, which will result in a single level array for either an array of any length or a single non-array object.

>> def f x
>>   [*x].inspect
>> end
=> nil
>> 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
>>   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]"
DigitalRoss
So you are saying if it is a single item it makes it a array with a single item in it?
tyndall
Yes, and if it already is an array it keeps it without adding a second array wrapper.
DigitalRoss