Finding if an array contains a data type

S

Sam Phoneix

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.
 
D

David Chelimsky

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
 
T

Tim Hunter

Sam said:
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.

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
 
C

Carlos J. Hernandez

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.
 
D

David Chelimsky

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
 
D

David Chelimsky

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.

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

Tim Hunter

David said:
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 :)
 
J

Joel VanderWerf

Sam said:
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
 
S

Sebastian Hungerecker

Tim said:
Also I can't ever
remember which order the arguments [of ===] go :)

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
 
D

dan yoder

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top