Finding if an array contains a data type

Say I wanted to see if an array contained a number or not. Would I use
the match method?

E.g.

x=[“a”,“b”,2, “c”]

puts(“This array contains numbers”) if x.match(/\d/)

I’m a real beginner at ruby, so simple explanations for simple folk
please. I appreciate your help.

On Jan 3, 2008 6:27 PM, Sam P. [email protected]
wrote:

Say I wanted to see if an array contained a number or not. Would I use
the match method?

E.g.

x=[“a”,“b”,2, “c”]

puts(“This array contains numbers”) if x.match(/\d/)

Not sure if this is the simplest way, but if you’re looking for actual
numbers (not strings that look like numbers) you could do this:

puts(“This array contains numbers”) if x.find {|n| Numeric === n}

Cheers,
David

David C. wrote:

puts(“This array contains numbers”) if x.find {|n| Numeric === n}

Spot on, thanks.

Several ways to test, but probably I’d like best

x=[“a”,“b”,2, “c”]
puts “This array contains numbers” if x.find{|t| t.kind_of?(Numeric)}

The method find is given to class Array by Enumerable, not so obvious.
Not knowing find nor kind_of?, I’d probably do

x=[“a”,“b”,2, “c”]
x.each { |t|
if t.to_s =~ /^\d+(.\d+)?$/ then
puts “This array contains numbers”
break
end
}

But that’s just ugly.

On Fri, 4 Jan 2008 09:27:05 +0900, “Sam P.”
[email protected] said:

Sam P. wrote:

I’m a real beginner at ruby, so simple explanations for simple folk
please. I appreciate your help.

Nice try, but match matches strings and you’re wanting numbers.

Note that the Array class includes the Enumerable module, so all methods
in Enumerable are available in Array. Enumerable has a method called
“any?” that we can use. Here’s what ri says about Enumerable#any?

$ ri Enumerable#any?
-------------------------------------------------------- Enumerable#any?
enum.any? [{|obj| block } ] => true or false

  Passes each element of the collection to the given block. The
  method returns true if the block ever returns a value other than
  false or nil. If the block is not given, Ruby adds an implicit
  block of {|obj| obj} (that is any? will return true if at least
  one of the collection members is not false or nil.

     %w{ ant bear cat}.any? {|word| word.length >= 3}   #=> true
     %w{ ant bear cat}.any? {|word| word.length >= 4}   #=> true
     [ nil, true, 99 ].any?                             #=> true

So, here’s how to use it:

irb(main):001:0> x=[“a”,“b”,2, “c”]
=> [“a”, “b”, 2, “c”]
irb(main):002:0> x.any? {|p| p.is_a? Numeric}
=> true

On Jan 3, 2008 6:52 PM, Tim H. [email protected] wrote:

So, here’s how to use it:

irb(main):001:0> x=[“a”,“b”,2, “c”]
=> [“a”, “b”, 2, “c”]
irb(main):002:0> x.any? {|p| p.is_a? Numeric}
=> true

Sam - I’d go with Tim’s suggestion (.any?) rather than what I proposed
(.find).

.find returns the first object in the Array, whereas .any? returns
boolean, which seems to be a better fit (semantically) for what you’re
after.

Cheers,
David

On Jan 3, 2008 6:58 PM, David C. [email protected] wrote:

.find returns the first object in the Array, whereas .any? returns
boolean, which seems to be a better fit (semantically) for what you’re
after.

Although I wonder what your opinion (Tim) is on is_a? vs ===.

David C. wrote:

Although I wonder what your opinion (Tim) is on is_a? vs ===.

My opinion carries no weight whatsoever, but fwiw, I always use is_a? or
kind_of? because it’s not obvious what === does. Also I can’t ever
remember which order the arguments go :slight_smile:

Tim H. wrote:

Also I can’t ever
remember which order the arguments [of ===] go :slight_smile:

Try to remember it like this: The one that defines the behaviour of ===
(i.e.
the class, range or regexp) goes first.
But yeah, I don’t usually explicitly use === either.

HTH,
Sebastian

Sam P. wrote:

Say I wanted to see if an array contained a number or not. Would I use
the match method?

E.g.

x=[“a”,“b”,2, “c”]

puts(“This array contains numbers”) if x.match(/\d/)

Another way, just for fun:

x=[“a”,“b”,2, “c”]
puts(“This array contains numbers”) unless x.grep(Numeric).empty?

Let’s take apart what that means:

  1. The Enumerable#grep method uses the “matching” operator === to search
    for all matches to the argument, which are collected into a new array.

  2. In this case, grep’s argument is a class, so each element of x is
    matched using the following condition: Numeric === the_element.

  3. When called on classes, === checks if the given object is a member of
    the class (or a descendent) or not.

But this is not the most efficient solution since it has to pass over
the entire collection (instead of stopping on the first match), and it
makes a new array with the results. It’s really only useful when you
need all matches, for some reason. Otherwise, follow the suggestion to
use #any? and #is_a? or #kind_of?.

References:

ri Module#===
ri Enumerable#grep

On Jan 3, 11:58 pm, Sebastian H. [email protected]
wrote:

But yeah, I don’t usually explicitly use === either.

I would say that === is more appropriate in the case where you are
generalizing and the thing you might match against will vary. This is
in fact what grep does - it will work on anything that responds to
===.

For example, it would be useful in the case of a find version of grep
(to solve the above problem with grep iterating over the whole array).
Let’s call it grep_first:

class Array ; def grep_first pat ; find { | el | pat === el } ; end ;
end
array = [‘foo’,‘bar’,2,‘7’,‘hi’ ]
array.grep_first Numeric # => 2
array.grep_first /\d/ # => ‘7’
array.grep_first ‘bar’ # => ‘bar’
array.grep_first ‘foobar’ # => nil

But if you specifically know you are matching a type then I think
is_a or kind_of is probably better. Interested in others’ take on
this.

Regards,
Dan


Dan Y.
dev.zeraweb.com