[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Checking an array for an item

Sam Phoneix

1/4/2008 3:05:00 PM

How come this code doesn't return "true" for the following?

x = [1,2,3]

puts(x.include?(Fixnum))



Thanks
--
Posted via http://www.ruby-....

8 Answers

David Chelimsky

1/4/2008 3:15:00 PM

0

On Jan 4, 2008 9:05 AM, Sam Phoneix <dominicjefferies@yahoo.co.uk> wrote:
> How come this code doesn't return "true" for the following?
>
> x = [1,2,3]
>
> puts(x.include?(Fixnum))

It uses ==, not ===.

$ri Enumerable#include?

---------------------------------------------------- Enumerable#include?
enum.include?(obj) => true or false
enum.member?(obj) => true or false
------------------------------------------------------------------------
Returns +true+ if any member of _enum_ equals _obj_. Equality is
tested using +==+.

Tim Hunter

1/4/2008 3:16:00 PM

0

Sam Phoneix wrote:
> How come this code doesn't return "true" for the following?
>
> x = [1,2,3]
>
> puts(x.include?(Fixnum))
>
>
>
> Thanks

Because include? doesn't test the class of an object, it tests for the
presence of an object. The ri command is your friend here:

$ ri Array.include?
--------------------------------------------------------- Array#include?
array.include?(obj) -> true or false
------------------------------------------------------------------------
Returns true if the given object is present in self (that is, if
any object == anObject), false otherwise.

a = [ "a", "b", "c" ]
a.include?("b") #=> true
a.include?("z") #=> false


--
RMagick: http://rmagick.ruby...
RMagick 2: http://rmagick.ruby...rmagick2.html

Thomas Wieczorek

1/4/2008 3:44:00 PM

0

On Jan 4, 2008 4:05 PM, Sam Phoneix <dominicjefferies@yahoo.co.uk> wrote:
> How come this code doesn't return "true" for the following?
>
> x = [1,2,3]
>
> puts(x.include?(Fixnum))
>
>

You could try something like:

class Array
def include_class?(klass)
if self.detect { |x| x.class == klass }
return true
else
return false
end
end
end

Giles Bowkett

1/4/2008 4:26:00 PM

0

> How come this code doesn't return "true" for the following?
>
> x = [1,2,3]
>
> puts(x.include?(Fixnum))

In addition to the reasons other people mentioned, Fixnum is an actual
object in Ruby. You could put it in an array if you wanted:

classes_that_start_with_f = [Fixnum, File, FizzBuzz]

classes_that_start_with_f.include?(Fixnum) # returns true

That's why it doesn't work like you expect; because #include?(Fixnum)
is for finding the actual Fixnum class object.

To get what you want the best approach is map, or one of a few
functions similar to map, such as collect or inject:

>> [1,2,3].map {|number| number.is_a? Fixnum}
=> [true, true, true]
>> [1,2,3,"asdfasdfasdf"].map {|number| number.is_a? Fixnum}
=> [true, true, true, false]
>> [1,2,3,"asdfasdfasdf"].map {|number| number.is_a? Fixnum}.include?(true)
=> true

class Array
def include_class?(klass)
map do |thing|
thing.is_a? klass
end.include?(true)
end
end

>> [1,2,3].include_class?(Fixnum)
=> true

Thomas Wieczorek's solution is good too. #detect is a cousin of #map.

--
Giles Bowkett

Podcast: http://hollywoodgrit.bl...
Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...
Tumblelog: http://giles....

Sam Phoneix

1/4/2008 7:51:00 PM

0

Giles Bowkett wrote:
>>> [1,2,3].map {|number| number.is_a? Fixnum}
> => [true, true, true]

Thanks
--
Posted via http://www.ruby-....

Rick DeNatale

1/4/2008 8:12:00 PM

0

On Jan 4, 2008 11:25 AM, Giles Bowkett <gilesb@gmail.com> wrote:
> > How come this code doesn't return "true" for the following?
> >
> > x = [1,2,3]
> >
> > puts(x.include?(Fixnum))

> To get what you want the best approach is map, or one of a few
> functions similar to map, such as collect or inject:

Well, if you're trying to find out if the array contains at least one
Fixnum then this isn't really the best way. Instead I'd use

x.any? {|obj| Fixnum === obj }

which returns a single boolean, and only looks at as many elements of
the array as it needs to.

Alternately one could use

x.find {|obj| Fixnum === obj }

which will return either the first Fixnum in the array, or nil if
their isn't one, which can be used the same way as a boolean value in
almost all cases.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...

Giles Bowkett

1/4/2008 10:10:00 PM

0

> Well, if you're trying to find out if the array contains at least one
> Fixnum then this isn't really the best way. Instead I'd use
>
> x.any? {|obj| Fixnum === obj }
>
> which returns a single boolean, and only looks at as many elements of
> the array as it needs to.

Yeah, I think that's the best way too.

--
Giles Bowkett

Podcast: http://hollywoodgrit.bl...
Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...
Tumblelog: http://giles....

Giles Bowkett

1/4/2008 10:11:00 PM

0

> > Well, if you're trying to find out if the array contains at least one
> > Fixnum then this isn't really the best way. Instead I'd use
> >
> > x.any? {|obj| Fixnum === obj }
> >
> > which returns a single boolean, and only looks at as many elements of
> > the array as it needs to.
>
> Yeah, I think that's the best way too.

Wait, no I don't. I'd say switch === with .is_a? and that would be the
best way. More readable, and allows you to avoid the question "what is
===?"

Generally I think you should avoid === unless implementing it on new
classes for the sake of case/switch statements.

--
Giles Bowkett

Podcast: http://hollywoodgrit.bl...
Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...
Tumblelog: http://giles....