Problem with Array#delete - RUBY

This is a discussion on Problem with Array#delete - RUBY ; Hello, I'm baffled by the following problem: I have an Account class and an external array that keeps them in a list. I'm trying to delete the account objects one at a time as needed, by: class Account def quit ...

+ Reply to Thread
Page 1 of 2 1 2 LastLast
Results 1 to 10 of 16

Problem with Array#delete

  1. Default Problem with Array#delete

    Hello, I'm baffled by the following problem:

    I have an Account class and an external array that keeps them in a list. I'm
    trying to delete the account objects one at a time as needed, by:

    class Account
    def quit
    array_name.delete self
    end
    end

    However, this is deleting every account in the list (array_name == []). I've
    verified that the account objects are unique. Just for an example, this is
    the equivalent of what's happening:

    class Account
    def quit arr
    arr.delete self
    end
    end

    a1 = Account.new
    a2 = Account.new
    arr = []
    arr << a1
    arr << a2
    a1.quit arr
    arr #=> []


    Has anyone else experienced this problem, or know what the likely cause is? I
    have other arrays that work in the exact same fashion and work as expected.

    Thank you for any help,
    Matt


  2. Default Re: Problem with Array#delete

    On Aug 18, 2007, at 12:59 AM, Matthew B Gardner wrote:

    > Hello, I'm baffled by the following problem:
    >
    > I have an Account class and an external array that keeps them in a
    > list. I'm
    > trying to delete the account objects one at a time as needed, by:
    >
    > class Account
    > def quit
    > array_name.delete self
    > end
    > end
    >
    > However, this is deleting every account in the list (array_name ==
    > []). I've
    > verified that the account objects are unique. Just for an example,
    > this is
    > the equivalent of what's happening:
    >
    > class Account
    > def quit arr
    > arr.delete self
    > end
    > end
    >
    > a1 = Account.new
    > a2 = Account.new
    > arr = []
    > arr << a1
    > arr << a2
    > a1.quit arr
    > arr #=> []
    >
    > Has anyone else experienced this problem, or know what the likely
    > cause is? I
    > have other arrays that work in the exact same fashion and work as
    > expected.


    I ran your code and I didn't have a problem: it did what you
    expected. Are you sure that the code you posted is exactly the same
    as the code that is giving you trouble?

    Regards, Morton


  3. Default Re: Problem with Array#delete

    Matthew B Gardner wrote:
    > Hello, I'm baffled by the following problem:
    >
    > I have an Account class and an external array that keeps them in a list. I'm
    > trying to delete the account objects one at a time as needed, by:
    >
    > class Account
    > def quit
    > array_name.delete self
    > end
    > end
    >
    > However, this is deleting every account in the list (array_name == []). I've
    > verified that the account objects are unique. Just for an example, this is
    > the equivalent of what's happening:
    >
    > class Account
    > def quit arr
    > arr.delete self
    > end
    > end
    >
    > a1 = Account.new
    > a2 = Account.new
    > arr = []
    > arr << a1
    > arr << a2
    > a1.quit arr
    > arr #=> []
    >
    >
    > Has anyone else experienced this problem, or know what the likely cause is? I
    > have other arrays that work in the exact same fashion and work as expected.
    >
    > Thank you for any help,
    > Matt
    >
    >


    Wow, that was a well-asked question. This seems like a Ruby bug, though
    I can't reproduce it. When I run the code you posted, arr[] still
    contains a2 (as it should). I am using Ruby 1.8.6 (on Linux). What are
    you using?

    Dan


  4. Default Re: Problem with Array#delete

    Sorry, I only meant the code I posted as an example of what is happening --
    the actual code would be a little hard to gather and format, but I will do so
    if the following isn't enough information:

    ruby -v #=> ruby 1.8.4 (2005-12-24) [i486-linux]

    Ok, I threw this code in to gather some info, and following it is the
    printout:

    p world.characters.class
    p world.characters.size
    world.characters.each do |ch|
    p ch.class
    p ch.object_id
    end
    world.characters.delete(self)
    p world.characters

    Array
    2
    Character
    -607336504
    Character
    -607410834
    []

    Do I need to format up the code, or is there something telling from the
    information here?

    Thanks,
    Matt

    On Saturday 18 August 2007 02:17, Morton Goldberg wrote:
    > On Aug 18, 2007, at 12:59 AM, Matthew B Gardner wrote:
    > > Hello, I'm baffled by the following problem:
    > >
    > > I have an Account class and an external array that keeps them in a
    > > list. I'm
    > > trying to delete the account objects one at a time as needed, by:
    > >
    > > class Account
    > > def quit
    > > array_name.delete self
    > > end
    > > end
    > >
    > > However, this is deleting every account in the list (array_name ==
    > > []). I've
    > > verified that the account objects are unique. Just for an example,
    > > this is
    > > the equivalent of what's happening:
    > >
    > > class Account
    > > def quit arr
    > > arr.delete self
    > > end
    > > end
    > >
    > > a1 = Account.new
    > > a2 = Account.new
    > > arr = []
    > > arr << a1
    > > arr << a2
    > > a1.quit arr
    > > arr #=> []
    > >
    > > Has anyone else experienced this problem, or know what the likely
    > > cause is? I
    > > have other arrays that work in the exact same fashion and work as
    > > expected.

    >
    > I ran your code and I didn't have a problem: it did what you
    > expected. Are you sure that the code you posted is exactly the same
    > as the code that is giving you trouble?
    >
    > Regards, Morton



  5. Default Re: Problem with Array#delete

    On 18.08.2007 08:34, Matthew B Gardner wrote:
    > Sorry, I only meant the code I posted as an example of what is happening --
    > the actual code would be a little hard to gather and format, but I will do so
    > if the following isn't enough information:
    >
    > ruby -v #=> ruby 1.8.4 (2005-12-24) [i486-linux]
    >
    > Ok, I threw this code in to gather some info, and following it is the
    > printout:
    >
    > p world.characters.class
    > p world.characters.size
    > world.characters.each do |ch|
    > p ch.class
    > p ch.object_id
    > end
    > world.characters.delete(self)
    > p world.characters
    >
    > Array
    > 2
    > Character
    > -607336504
    > Character
    > -607410834
    > []
    >
    > Do I need to format up the code, or is there something telling from the
    > information here?



    The crucial bit is missing: how did you define ==, eql? and hash in your
    class? Did you define them? If not, using Struct might help because
    that gives you those methods for free:

    YourClass = Struct.new :name, ther_field do
    def method_you_need
    end
    end

    Then eql?, == and hash will be implemented in terms of "name" and
    "other_field".

    Kind regards

    robert

  6. Default Re: Problem with Array#delete

    I went a little different route, but that was indeed the problem. I just
    defined == in my class, which I guess was comparing the class of the object
    instead of the object_id. I did:

    def == obj
    self.equal?(obj)
    end

    If you have time, or if someone else does, is there a quick explanation of why
    this happened in this instance, but not with similar classes that function
    fine with essentially duplicate methods of adding to and deleting from
    arrays? Hopefully I can avoid future problems if I understand what's
    happening (I'm a hobby programmer, so I lack some technical expertise).

    Thank you, and the other repliers, for the help -- it's very much appreciated.
    -Matt

    On Saturday 18 August 2007 05:09, Robert Klemme wrote:
    > On 18.08.2007 08:34, Matthew B Gardner wrote:
    > > Sorry, I only meant the code I posted as an example of what is happening
    > > -- the actual code would be a little hard to gather and format, but I
    > > will do so if the following isn't enough information:
    > >
    > > ruby -v #=> ruby 1.8.4 (2005-12-24) [i486-linux]
    > >
    > > Ok, I threw this code in to gather some info, and following it is the
    > > printout:
    > >
    > > p world.characters.class
    > > p world.characters.size
    > > world.characters.each do |ch|
    > > p ch.class
    > > p ch.object_id
    > > end
    > > world.characters.delete(self)
    > > p world.characters
    > >
    > > Array
    > > 2
    > > Character
    > > -607336504
    > > Character
    > > -607410834
    > > []
    > >
    > > Do I need to format up the code, or is there something telling from the
    > > information here?

    >
    > The crucial bit is missing: how did you define ==, eql? and hash in your
    > class? Did you define them? If not, using Struct might help because
    > that gives you those methods for free:
    >
    > YourClass = Struct.new :name, ther_field do
    > def method_you_need
    > end
    > end
    >
    > Then eql?, == and hash will be implemented in terms of "name" and
    > "other_field".
    >
    > Kind regards
    >
    > robert



  7. Default Re: Problem with Array#delete

    On 18.08.2007 11:44, Matthew B Gardner wrote:
    > I went a little different route, but that was indeed the problem. I just
    > defined == in my class, which I guess was comparing the class of the object
    > instead of the object_id. I did:
    >
    > def == obj
    > self.equal?(obj)
    > end
    >
    > If you have time, or if someone else does, is there a quick explanation of why
    > this happened in this instance,


    If you just defined == the way you presented above then the issue should
    not have occurred because equal? tests for identity. It's difficult to
    comment on fragments when the whole code is not presented.

    > but not with similar classes that function
    > fine with essentially duplicate methods of adding to and deleting from
    > arrays?


    I am not sure what you mean by this. Can you elaborate?

    > Hopefully I can avoid future problems if I understand what's
    > happening (I'm a hobby programmer, so I lack some technical expertise).


    There are some concepts you should keep in mind that have some
    similarities and will typically wreck havoc on your code when confused.
    Both define relations (in the mathematical sense) on objects.

    First, there is "identity". Two objects are identical when they are
    actually just one, i.e. the same instance.

    Then, there is equivalence. Equivalence is defined per class. For
    example two strings containing the same sequence of characters are
    equivalent. Sometimes only identical instances are equivalent.

    Now, these different concepts are implemented in Ruby via different methods:
    eql? and == implement equivalence
    equal? implements identity

    Most containers (an Array is a container) use equivalence, namely
    implemented via eql? to test whether some objects match (e.g. for
    deletion), because it is the more flexible and more useful concept.
    (Think of an Array of Strings and you want to delete one of them with a
    certain character sequence, you would want to provide a string with that
    sequence as template and not the exact same object in the array - which
    you might not know beforehand.)

    Now, there is a slight twist: since for some algorithms it's not
    efficient to compare something against all elements in the container
    (for example, Array#uniq would have to compare every element of the
    array with every other element which is O(n*n), i.e. if you double the
    elements in the Array you quadruple the number of comparisons
    necessary). In those cases (unfortunately they are not all documented)
    typically a Hash is used behind the scenes. For objects to work
    properly as Hash key methods eql? *and* hash need to be implemented
    properly.

    Consequence is, that you should always implement eql? and hash (and also
    == for consistency) reasons *if* you plan to use instances of your class
    in these circumstances *and* want to define equivalence different than
    via identity (which happens to be the default implementation in class
    Object). Typically you will choose some fields for this and you must
    also make sure that equivalent instances yield the same (!) hash code.
    Normally you do that by applying some math operation (binary XOR is
    frequently used, because it's fast and guarantees that all values used
    influence the result) on the hash values of those members that you
    determine as key elements for equivalence.

    The easiest way to do that is by using Struct, because that will
    generate a class with all the necessary methods. Example:

    # name and age are key for Foo
    Foo = Struct.new :name, :age do
    attr_accessor :unimportant_other_attribute
    end


    irb(main):007:0> f1 = Foo.new("a", 10)
    => #<struct Foo name="a", age=10>
    irb(main):008:0> f2 = Foo.new("a", 10)
    => #<struct Foo name="a", age=10>
    irb(main):009:0> f1.hash
    => -2186440
    irb(main):010:0> f2.hash
    => -2186440
    irb(main):011:0> f1.eql? f2
    => true
    irb(main):012:0> f1 == f2
    => true
    irb(main):013:0> f1.equal? f2
    => false
    irb(main):014:0> f1.unimportant_other_attribute = "bar"
    => "bar"
    irb(main):015:0> f1.eql? f2
    => true
    irb(main):016:0> f1.name = "hello"
    => "hello"
    irb(main):017:0> f1.eql? f2
    => false

    There is another thing you should be aware: numbers in Ruby actually
    implement *two* different equivalence relations:

    irb(main):018:0> 1 == 1.0
    => true
    irb(main):019:0> 1.eql? 1.0
    => false
    irb(main):020:0> 1.hash
    => 3
    irb(main):021:0> 1.0.hash
    => 233071

    But most classes treat == and eql? synonym.

    Next week we'll dive into ordering and operator <=>. :-))

    Kind regards

    robert

  8. Default Re: Problem with Array#delete

    > I went a little different route, but that was indeed the problem. I just=
    =20
    > defined =3D=3D in my class, which I guess was comparing the class of the =

    object=20
    > instead of the object_id. I did:
    >=20
    > def =3D=3D obj
    > =A0=A0=A0=A0=A0=A0self.equal?(obj)
    > end


    Ok, so it looks like this didn't work so well after all. Initially, I thoug=
    ht=20
    it did because I reloaded the character.rb file while the program was runni=
    ng=20
    and it worked fine. However, when I shutdown the program and started it bac=
    k=20
    up, I experienced the same problem (though it again worked after reloading=
    =20
    the file). I'll post all the necessary code:

    def world
    returns the world object
    end

    class World
    def initialize
    characters =3D []
    end
    end

    class Account
    def foo
    @character =3D Character.new()
    world.characters << @character
    end
    end

    class Character
    def quit
    p self.object_id
    p world.characters.class
    p world.characters.size
    world.characters.each do |ch|
    p ch.class
    p ch.object_id
    end
    world.characters.delete(self)
    p world.characters
    end
    end

    This is the output from Character#quit, with two character objects in the=20
    world#characters array:

    =2D607170236
    Array
    2
    Character
    =2D607170236
    Character
    =2D607240286
    []

    As you can see, both Character objects are being deleted when only the firs=
    t=20
    should be (at least as far as my intention). In an attempt to fix this, I=20
    added the following method:

    class Character
    def =3D=3D obj
    self.equal?(obj)
    end
    end

    I thought this did fix it, because I reloaded the file and tested it -- and=
    it=20
    only deleted the targeted object. However, when I restarted the program, it=
    =20
    didn't work and deleted both objects again. Without changing anything, and=
    =20
    just reloading the file while the program was still running, it worked as=20
    intended again and deleted only the targeted object.

    I have an Account class that utilizes World#accounts (an Array object) in t=
    he=20
    exact same way that Character utilizes World#characters, and the deletion o=
    f=20
    accounts works fine.

    Robert, thank you for your reply -- I hope that this answers the noted=20
    questions that you had, and maybe even provides some more insight into what=
    =20
    the problem might be. Is there an explanation for why the Character#=3D=3D =
    method=20
    works after being reloaded, but not at start time? Also, Robert, I reviewed=
    =20
    the portion of your reply regarding a Struct object, and it doesn't look li=
    ke=20
    it would be beneficial in my case -- I'm just trying to add and delete sing=
    le=20
    instances of a class from an array -- but I could be wrong?

    Thanks again for any help,
    Matt


  9. Default Re: Problem with Array#delete

    --1926193751-2036615464-1187462143=:4504
    Content-Type: MULTIPART/MIXED; BOUNDARY="1926193751-2036615464-1187462143=:4504"

    This message is in MIME format. The first part should be readable text,
    while the remaining parts are likely unreadable without MIME-aware tools.

    --1926193751-2036615464-1187462143=:4504
    Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed
    Content-Transfer-Encoding: QUOTED-PRINTABLE

    Hi --

    On Sun, 19 Aug 2007, Matthew B Gardner wrote:

    >> I went a little different route, but that was indeed the problem. I just
    >> defined =3D=3D in my class, which I guess was comparing the class of the=

    object
    >> instead of the object_id. I did:
    >>
    >> def =3D=3D obj
    >> =A0=A0=A0=A0=A0=A0self.equal?(obj)
    >> end

    >
    > Ok, so it looks like this didn't work so well after all. Initially, I tho=

    ught
    > it did because I reloaded the character.rb file while the program was run=

    ning
    > and it worked fine. However, when I shutdown the program and started it b=

    ack
    > up, I experienced the same problem (though it again worked after reloadin=

    g
    > the file). I'll post all the necessary code:
    >
    > def world
    > =09returns the world object
    > end
    >
    > class World
    > =09def initialize
    > =09=09characters =3D []
    > =09end
    > end


    Can you un-pseudo-code the code to the point where it does (or doesn't
    do) what you want? I can't make the thing you're describing happen
    when I try to get the code up and running, so a complete (non-)working
    example would be good.


    David

    --=20
    * Books:
    RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
    RUBY FOR RAILS (http://www.manning.com/black)
    * Ruby/Rails training
    & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
    --1926193751-2036615464-1187462143=:4504--
    --1926193751-2036615464-1187462143=:4504--


  10. Default Re: Problem with Array#delete

    Thank you to everyone who has tried to help me with this today -- I know for
    certain -what- the problem is now, after adding in some testing. My Character
    class, for whatever reason, is using == to evaluate class. So, when I am
    trying to use Array#delete (array.delete(self) for a Character object), it's
    deleting every Character object in that array instead of just that single
    instance. I've tried to fix this issue by defining the == method in my
    Character class like this:

    def Character
    def == obj
    self.equal?(obj)
    end
    end

    However, this doesn't initially work -- I have to reload the file during
    runtime for it to utilize the above method. For sake of clarity, this is what
    I mean:

    Start program...
    a = Character.new
    b = Character.new
    a == b #=> true
    Reload character.rb file while program is running...
    a == b #=> false

    Hopefully that gets my meaning across. I'm not sure why Character#== isn't
    initially getting used, or if there's something wrong with my declaration.
    I'm also not sure why Character#== (prior to my defining Character#==) is
    comparing class and my other classes aren't.

    I hope that this description is satisfactory -- and thank you for any help
    that can be offered.
    -Matt

    On Saturday 18 August 2007 14:35, David A. Black wrote:


+ Reply to Thread
Page 1 of 2 1 2 LastLast

Similar Threads

  1. how to delete Array
    By Application Development in forum RUBY
    Replies: 4
    Last Post: 11-09-2007, 05:47 AM
  2. how to delete array
    By Application Development in forum RUBY
    Replies: 20
    Last Post: 11-08-2007, 09:09 AM
  3. Array new followed by non-array delete - request for experience
    By Application Development in forum c++
    Replies: 18
    Last Post: 10-10-2007, 05:59 AM
  4. Reg. delete of an array of objects
    By Application Development in forum c++
    Replies: 3
    Last Post: 08-17-2007, 02:15 AM
  5. how to delete an array and re-use it?
    By Application Development in forum REXX
    Replies: 2
    Last Post: 11-10-2006, 01:55 PM