Checking an array for an item

Discussion in 'Ruby' started by Sam Phoneix, Jan 4, 2008.

  1. Sam Phoneix

    Sam Phoneix Guest

    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-forum.com/.
     
    Sam Phoneix, Jan 4, 2008
    #1
    1. Advertising

  2. On Jan 4, 2008 9:05 AM, Sam Phoneix <> 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 +==+.
     
    David Chelimsky, Jan 4, 2008
    #2
    1. Advertising

  3. Sam Phoneix

    Tim Hunter Guest

    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.rubyforge.org/
    RMagick 2: http://rmagick.rubyforge.org/rmagick2.html
     
    Tim Hunter, Jan 4, 2008
    #3
  4. On Jan 4, 2008 4:05 PM, Sam Phoneix <> 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
     
    Thomas Wieczorek, Jan 4, 2008
    #4
  5. > 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.blogspot.com
    Blog: http://gilesbowkett.blogspot.com
    Portfolio: http://www.gilesgoatboy.org
    Tumblelog: http://giles.tumblr.com
     
    Giles Bowkett, Jan 4, 2008
    #5
  6. Sam Phoneix

    Sam Phoneix Guest

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

    > => [true, true, true]


    Thanks
    --
    Posted via http://www.ruby-forum.com/.
     
    Sam Phoneix, Jan 4, 2008
    #6
  7. On Jan 4, 2008 11:25 AM, Giles Bowkett <> 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.denhaven2.com/
     
    Rick DeNatale, Jan 4, 2008
    #7
  8. Giles Bowkett, Jan 4, 2008
    #8
  9. > > 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.blogspot.com
    Blog: http://gilesbowkett.blogspot.com
    Portfolio: http://www.gilesgoatboy.org
    Tumblelog: http://giles.tumblr.com
     
    Giles Bowkett, Jan 4, 2008
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. D. Shane Fowlkes
    Replies:
    0
    Views:
    586
    D. Shane Fowlkes
    May 11, 2004
  2. D. Shane Fowlkes
    Replies:
    0
    Views:
    1,020
    D. Shane Fowlkes
    May 13, 2004
  3. Replies:
    7
    Views:
    319
    Gilles Ganault
    Jun 16, 2008
  4. Darrel
    Replies:
    2
    Views:
    355
    Darrel
    Apr 27, 2009
  5. Ven
    Replies:
    0
    Views:
    157
Loading...

Share This Page