Quiz #65, Principle of Great Surprise, and Array.delete sledgehammer

Discussion in 'Ruby' started by Dave Howell, Feb 4, 2006.

  1. Dave Howell

    Dave Howell Guest

    I thought I was actually going to enter my first RubyQuiz, but I've
    spent three times as much time trying to get Ruby to stop surprising me
    as I have trying to implement my algorithm, and I've had to abandon my
    effort since I don't have the time to spend. Sigh.

    Can somebody explain to me how I'm supposed to delete a *single*
    element from an array based on equivalence with an object? and get back
    said array with said element deleted?

    In other words....

    ar = [1, 2, 3, 8, 15, 15, 8]

    ar.delete_one_element!(15)
    => [1, 2, 3, 8, 15, 8]

    ar.delete_one_element!(14)
    => [1, 2, 3, 8, 15, 15, 8]

    ar.delete_one_element!(nil)
    => [1, 2, 3, 8, 15, 15, 8]

    I did find so many different ways of not doing this....

    Too enthusiastic....
    ar.delete(15)
    => 15
    ar
    => [1, 2, 3, 8, 8]

    Right results, wrong output...
    ar.slice!(ar.index(15))
    => 15
    ar
    => [1, 2, 3, 8, 15, 8]

    and also surprised me by not handling 'nil' as I wanted...
    ar.slice!(ar.index(13))
    TypeError: no implicit conversion from nil to integer
    from (irb):8:in `slice!'
    from (irb):8


    I mean, this seems so, er, obvious! "Please find one instance of this
    object in the array, and return to me the array without that object. If
    the array doesn't have that object, then just give the array back to
    me."

    Why isn't that the Ruby Way? What am I missing here?

    Help?
     
    Dave Howell, Feb 4, 2006
    #1
    1. Advertising

  2. T24gMi80LzA2LCBEYXZlIEhvd2VsbCA8Z3JvdXBzQGdyYW5kZmVud2ljay5uZXQ+IHdyb3RlOgo+
    IEkgbWVhbiwgdGhpcyBzZWVtcyBzbywgZXIsIG9idmlvdXMhICJQbGVhc2UgZmluZCBvbmUgaW5z
    dGFuY2Ugb2YgdGhpcwo+IG9iamVjdCBpbiB0aGUgYXJyYXksIGFuZCByZXR1cm4gdG8gbWUgdGhl
    IGFycmF5IHdpdGhvdXQgdGhhdCBvYmplY3QuIElmCj4gdGhlIGFycmF5IGRvZXNuJ3QgaGF2ZSB0
    aGF0IG9iamVjdCwgdGhlbiBqdXN0IGdpdmUgdGhlIGFycmF5IGJhY2sgdG8KPiBtZS4iCgogIGNs
    YXNzIEFycmF5CiAgICBkZWYgd2l0aG91dF9vbmUoZWxlbSkKICAgICAgbmV3ID0gc2VsZi5kdXAg
    IyBtYWtlIGEgY29weSBzbyB0aGF0IHRoZSBvcmlnaW5hbCBpcyBub3QgY2hhbmdlZAogICAgICBu
    ZXcuZGVsZXRlX2F0KG5ldy5pbmRleChlbGVtKSkKICAgICAgbmV3CiAgICBlbmQKICBlbmQKCiAg
    WzEsMiwzLDQsNCw0LDUsNV0ud2l0aG91dF9vbmUoNCkgIz0+IFsxLDIsMyw0LDQsNSw1XQoKLUxl
    dmluCg==
     
    Levin Alexander, Feb 4, 2006
    #2
    1. Advertising

  3. On Feb 4, 2006, at 2:50 PM, Dave Howell wrote:

    > Can somebody explain to me how I'm supposed to delete a *single*
    > element from an array based on equivalence with an object? and get
    > back said array with said element deleted?


    I was just wanting this method yesterday, and not for the first
    time. Is there any good reason we can't have a delete_first() method
    for Array?

    James Edward Gray II
     
    James Edward Gray II, Feb 4, 2006
    #3
  4. Dave Howell

    Guest

    On Sun, 5 Feb 2006, Dave Howell wrote:

    > I thought I was actually going to enter my first RubyQuiz, but I've spent
    > three times as much time trying to get Ruby to stop surprising me as I have
    > trying to implement my algorithm, and I've had to abandon my effort since I
    > don't have the time to spend. Sigh.
    >
    > Can somebody explain to me how I'm supposed to delete a *single* element from
    > an array based on equivalence with an object? and get back said array with
    > said element deleted?
    >
    > In other words....
    >
    > ar = [1, 2, 3, 8, 15, 15, 8]
    >
    > ar.delete_one_element!(15)
    > => [1, 2, 3, 8, 15, 8]
    >
    > ar.delete_one_element!(14)
    > => [1, 2, 3, 8, 15, 15, 8]
    >
    > ar.delete_one_element!(nil)
    > => [1, 2, 3, 8, 15, 15, 8]
    >
    > I did find so many different ways of not doing this....
    >
    > Too enthusiastic....
    > ar.delete(15)
    > => 15
    > ar
    > => [1, 2, 3, 8, 8]
    >
    > Right results, wrong output...
    > ar.slice!(ar.index(15))
    > => 15
    > ar
    > => [1, 2, 3, 8, 15, 8]
    >
    > and also surprised me by not handling 'nil' as I wanted...
    > ar.slice!(ar.index(13))
    > TypeError: no implicit conversion from nil to integer
    > from (irb):8:in `slice!'
    > from (irb):8
    >
    >
    > I mean, this seems so, er, obvious! "Please find one instance of this object
    > in the array, and return to me the array without that object. If the array
    > doesn't have that object, then just give the array back to me."
    >
    > Why isn't that the Ruby Way? What am I missing here?
    >
    > Help?


    harp:~ > cat a.rb
    class Array
    def remove(*args) replace(self - args) end
    end

    a = %w( a b b )
    p a.delete_if{|x| x == "b"}

    a = %w( a b b )
    p(a.delete("b") && a)

    a = %w( a b b )
    p a.select{|x| x != "b"}

    a = %w( a b b )
    p a - ["b"]

    a = %w( a b b c )
    p a.remove("b", "c")


    harp:~ > ruby a.rb
    ["a"]
    ["a"]
    ["a"]
    ["a"]
    ["a"]

    there are probably more ways.

    hth.

    -a

    --
    happiness is not something ready-made. it comes from your own actions.
    - h.h. the 14th dali lama
     
    , Feb 4, 2006
    #4
  5. On Feb 4, 2006, at 3:50 PM, Dave Howell wrote:

    > I thought I was actually going to enter my first RubyQuiz, but I've
    > spent three times as much time trying to get Ruby to stop
    > surprising me as I have trying to implement my algorithm, and I've
    > had to abandon my effort since I don't have the time to spend. Sigh.
    >
    > Can somebody explain to me how I'm supposed to delete a *single*
    > element from an array based on equivalence with an object? and get
    > back said array with said element deleted?
    >
    > In other words....
    >
    > ar = [1, 2, 3, 8, 15, 15, 8]
    >
    > ar.delete_one_element!(15)
    > => [1, 2, 3, 8, 15, 8]
    >
    > ar.delete_one_element!(14)
    > => [1, 2, 3, 8, 15, 15, 8]
    >
    > ar.delete_one_element!(nil)
    > => [1, 2, 3, 8, 15, 15, 8]
    >
    > I did find so many different ways of not doing this....
    >
    > Too enthusiastic....
    > ar.delete(15)
    > => 15
    > ar
    > => [1, 2, 3, 8, 8]
    >
    > Right results, wrong output...
    > ar.slice!(ar.index(15))
    > => 15
    > ar
    > => [1, 2, 3, 8, 15, 8]
    >
    > and also surprised me by not handling 'nil' as I wanted...
    > ar.slice!(ar.index(13))
    > TypeError: no implicit conversion from nil to integer
    > from (irb):8:in `slice!'
    > from (irb):8
    >
    >
    > I mean, this seems so, er, obvious! "Please find one instance of
    > this object in the array, and return to me the array without that
    > object. If the array doesn't have that object, then just give the
    > array back to me."
    >
    > Why isn't that the Ruby Way? What am I missing here?
    >
    > Help?
    >
    >
    >
    >

    require 'enumerator'
    class Array
    def delete_one_element(x = nil)
    if block_given?
    tester = lambda { |item| yield(item) }
    else
    tester = lambda { |item| item == x }
    end
    index_of_element = self.to_enum:)each_index).find { |i|
    tester.call(self) }
    unless index_of_element.nil?
    self.delete_at(index_of_element)
    end
    self
    end
    end
     
    Logan Capaldo, Feb 4, 2006
    #5
  6. T24gMi80LzA2LCBXaWxzb24gQmlsa292aWNoIDx3aWxzb25iQGdtYWlsLmNvbT4gd3JvdGU6Cj4g
    T24gMi80LzA2LCBEYXZlIEhvd2VsbCA8Z3JvdXBzQGdyYW5kZmVud2ljay5uZXQ+IHdyb3RlOgo+
    Cj4gU29tZW9uZSB3aWxsIHByb2JhYmx5IHBvc3QgYSBzb2x1dGlvbiB0aGF0IHVzZXMgaW5qZWN0
    LCB0aG91Z2guIEhlaC4KCmNsYXNzIEVudW1lcmFibGUKICBkZWYgZGVsZXRlX29uZV9vZihvYmop
    CiAgICBzZWxmLmluamVjdChbXSxmYWxzZSkgeyB8KGFyciwgYWxyZWFkeV9kZWxldGVkKSwgZWxl
    bXwKICAgICAgYXJyIDw8IGVsZW0gdW5sZXNzIGVsZW0gPT0gb2JqIGFuZCBub3QgYWxyZWFkeV9k
    ZWxldGVkCiAgICAgIGFscmVhZHlfZGVsZXRlZCA9IHRydWUgaWYgZWxlbSA9PSBvYmoKICAgICAg
    W2FyciwgYWxyZWFkeV9kZWxldGVkXQogICAgfVswXQogIGVuZAplbmQKCi4uLiB0aGlzIGlzIHVu
    dGVzdGVkCgotTGV2aW4sIHNjbnIK
     
    Levin Alexander, Feb 4, 2006
    #6

  7. > Why isn't that the Ruby Way? What am I missing here?
    >
    > Help?


    You obviously know how to code such a method yourself and i can't answer
    why for example Array#- doesn't work that way (had to learn that myself).

    The shortest solution i came up with is

    ar = [1, 2, 3, 8, 15, 15, 8]

    p ar.values_at(*(0...ar.size).to_a - [ar.index(15)])
    => [1, 2, 3, 8, 15, 8]

    p ar.values_at(*(0...ar.size).to_a - [ar.index(14)])
    => [1, 2, 3, 8, 15, 15, 8]

    p ar.values_at(*(0...ar.size).to_a - [ar.index(nil)])
    => [1, 2, 3, 8, 15, 15, 8]

    cheers

    Simon
     
    Simon Kröger, Feb 4, 2006
    #7
  8. Dave Howell

    Dave Howell Guest

    On Feb 4, 2006, at 13:22, Simon Kr=F6ger wrote:

    >
    >> Why isn't that the Ruby Way? What am I missing here?
    >> Help?

    >
    > You obviously know how to code such a method yourself and i can't=20
    > answer why for example Array#- doesn't work that way (had to learn=20
    > that myself).


    Well, actually, no, I don't. Here's what I bashed together:

    class Array
    def delete_single(element)
    if index=3Dself.index(element) then
    self.slice!(index,1)
    self
    else
    nil
    end
    end
    end

    It was originally going to be similar to .delete until I realized that=20=

    delete didn't return the array, but rather, everything *but* the=20
    array. And it had an optional "yield." I'm mystified as to how to make=20=

    THAT part work, since neither ri nor the Pickaxe book gave me any hint=20=

    at all as to how to detect IF a block is present, and yield if it is.=20
    Just using "yield" got me an error since I wasn't using a block in this=20=

    case.

    And even the above code took me hours to figure out, and I don't really=20=

    understand why it works. Well, that's not true, but I don't understand=20=

    it well enough to be able to figure out if there's a shorter way to do=20=

    it. I got that far by noticing what Pickaxe said about Array.slice!

    Equivalent to
    def slice!(*args)
    result =3D self[*args]
    self[*args] =3D nil
    result
    end

    which basically whispered to me "you have to return something other=20
    than the result of your deletion...." So I tried a couple things until=20=

    something worked. {shrug}

    > The shortest solution i came up with is
    >
    > ar =3D [1, 2, 3, 8, 15, 15, 8]
    >
    > p ar.values_at(*(0...ar.size).to_a - [ar.index(15)])
    > =3D> [1, 2, 3, 8, 15, 8]
    >
    > p ar.values_at(*(0...ar.size).to_a - [ar.index(14)])
    > =3D> [1, 2, 3, 8, 15, 15, 8]
    >
    > p ar.values_at(*(0...ar.size).to_a - [ar.index(nil)])
    > =3D> [1, 2, 3, 8, 15, 15, 8]


    Wow. I don't understand this one at all. The "-" operator also was=20
    massively destructive, removing all duplicates when used. I'm going to=20=

    have to look up the * operator (as I recall, it's one of those really=20
    strange-and-clever Ruby things) to see what might be going on here.

    Oh! Oh oh oh!

    My, that's very clever. Create an array containing the *index values*=20
    of the "real" array. They are, of course, each unique. Array-subtract=20
    the index value for the element you want to remove. Array-subtracting=20
    "nil" has no effect but isn't an error. Then use the remaining index=20
    values to copy those elements out of the original "real" array.

    Although I'm still going to have to look up what the * is=20
    accomplishing. :)
     
    Dave Howell, Feb 4, 2006
    #8
  9. Dave Howell

    Dave Howell Guest

    On Feb 4, 2006, at 13:10, Logan Capaldo wrote:

    > if block_given?


    Aha!

    <checks index of Pickaxe>

    I see. It's in there, but buried near the end of a section in the
    middle of the discussion on blocks.

    Time for some more highlighting....
     
    Dave Howell, Feb 4, 2006
    #9
  10. optional yield -- was Re: Quiz #65, Principle of Great Surprise,and Array.delete sledgehammer

    Dave Howell wrote:
    > And it had an optional "yield." I'm mystified as to how to make THAT
    > part work, since neither ri nor the Pickaxe book gave me any hint at all
    > as to how to detect IF a block is present, and yield if it is. Just
    > using "yield" got me an error since I wasn't using a block in this case.


    Use Kernel.block_given?, like this:

    def one_two_three
    if block_given?; yield 1; yield 2; yield 3;
    else [1,2,3]
    end
    end

    See the PickAxe, in the chapter on blocks and iterators, page 51.

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, Feb 4, 2006
    #10
  11. On Feb 4, 2006, at 3:49 PM, Dave Howell wrote:

    >
    > On Feb 4, 2006, at 13:09, James Edward Gray II wrote:
    >
    >> On Feb 4, 2006, at 2:50 PM, Dave Howell wrote:
    >>
    >>> Can somebody explain to me how I'm supposed to delete a *single*
    >>> element from an array based on equivalence with an object? and
    >>> get back said array with said element deleted?

    >>
    >> I was just wanting this method yesterday, and not for the first
    >> time. Is there any good reason we can't have a delete_first()
    >> method for Array?

    >
    > Wouldn't delete_first still ought to return "_obj_ or nil"?


    Good point. You are probably right.

    James Edward Gray II
     
    James Edward Gray II, Feb 4, 2006
    #11
  12. Dave Howell

    Dave Howell Guest

    On Feb 4, 2006, at 13:10, wrote:

    > On Sun, 5 Feb 2006, Dave Howell wrote:
    >>
    >> Can somebody explain to me how I'm supposed to delete a *single*
    >> element from an array based on equivalence with an object? and get
    >> back said array with said element deleted?
    >>
    >> In other words....
    >>
    >> ar = [1, 2, 3, 8, 15, 15, 8]
    >>
    >> ar.delete_one_element!(15)
    >> => [1, 2, 3, 8, 15, 8]
    >>
    >> ar.delete_one_element!(14)
    >> => [1, 2, 3, 8, 15, 15, 8]
    >>
    >> ar.delete_one_element!(nil)
    >> => [1, 2, 3, 8, 15, 15, 8]
    >>
    >> I did find so many different ways of not doing this....
    >>


    > class Array
    > def remove(*args) replace(self - args) end
    > end
    >
    > a = %w( a b b )
    > p a.delete_if{|x| x == "b"}
    > p(a.delete("b") && a)
    > p a.select{|x| x != "b"}
    > p a - ["b"]
    > p a.remove("b", "c")
    >
    > all return
    > ["a"]


    This is just a list of many other ways to not do what I want, yes?
    <scratch head>
     
    Dave Howell, Feb 4, 2006
    #12
  13. On 2/4/06, Dave Howell <> wrote:
    >
    > On Feb 4, 2006, at 13:10, Wilson Bilkovich wrote:
    >
    > > If I'm understanding you properly, this is one way:
    > >
    > > class Array
    > > def delete_one_element!(value)
    > > return self unless i =3D self.index(value)
    > > self =3D nil
    > > self.compact!
    > > end
    > > end
    > >

    >
    > You are, but it isn't. I might well have "nil" as a legitimate item in
    > the array, and .compact would erase all of them. I definitely want a
    > solution that can _never_ reduce the size of my array by more than one
    > element.
    >


    OK.. Here's a safer version:
    class Array
    def delete_first(value)
    return self unless i =3D self.index(value)
    self.delete_at(i)
    self
    end
    end

    irb(main):013:0> a =3D [1,2,3,8,15,15,8]
    =3D> [1, 2, 3, 8, 15, 15, 8]
    irb(main):014:0> a.delete_first(15)
    =3D> [1, 2, 3, 8, 15, 8]
    irb(main):015:0>
     
    Wilson Bilkovich, Feb 5, 2006
    #13
  14. Dave Howell

    Guest

    On Sun, 5 Feb 2006, Dave Howell wrote:

    > On Feb 4, 2006, at 13:10, wrote:
    >
    >> On Sun, 5 Feb 2006, Dave Howell wrote:
    >>>
    >>> Can somebody explain to me how I'm supposed to delete a *single* element
    >>> from an array based on equivalence with an object? and get back said array
    >>> with said element deleted?
    >>>
    >>> In other words....
    >>>
    >>> ar = [1, 2, 3, 8, 15, 15, 8]
    >>>
    >>> ar.delete_one_element!(15)
    >>> => [1, 2, 3, 8, 15, 8]
    >>>
    >>> ar.delete_one_element!(14)
    >>> => [1, 2, 3, 8, 15, 15, 8]
    >>>
    >>> ar.delete_one_element!(nil)
    >>> => [1, 2, 3, 8, 15, 15, 8]
    >>>
    >>> I did find so many different ways of not doing this....
    >>>

    >
    >> class Array
    >> def remove(*args) replace(self - args) end
    >> end
    >>
    >> a = %w( a b b )
    >> p a.delete_if{|x| x == "b"}
    >> p(a.delete("b") && a)
    >> p a.select{|x| x != "b"}
    >> p a - ["b"]
    >> p a.remove("b", "c")
    >>
    >> all return
    >> ["a"]

    >
    > This is just a list of many other ways to not do what I want, yes? <scratch
    > head>



    sorry. didn't read closely enough:

    harp:~ > cat a.rb
    class Array
    def remove(elem) delete_at(index(elem)) rescue nil; self end
    end

    a = [1, 2, 3, 8, 15, 15, 8]
    p a.remove(15)


    harp:~ > ruby a.rb
    [1, 2, 3, 8, 15, 8]

    though i'll say that not raising an error when the element is not found is an
    amazingly bad idea that would mask many bugs (imagine an algorithm that should
    sometimes remove things but __never__ does)

    regards.

    -a

    --
    happiness is not something ready-made. it comes from your own actions.
    - h.h. the 14th dali lama
     
    , Feb 5, 2006
    #14
  15. Dave Howell

    Adam Shelly Guest

    On 2/4/06, Dave Howell <> wrote:
    >
    > ... . The "-" operator also was
    > massively destructive, removing all duplicates when used.


    I ran into that problem too when I was coding the quiz.
    Does anyone else find it strange that a + b - b !=3D a if a contains
    duplicates of any element in b?

    To finish the quiz, I added this method:

    class Array
    def subtract arr
    return clear if arr=3D=3Dself
    arr.each{|e| if (n=3Dindex(e)) then delete_at(n); end }
    self
    end
    end

    a =3D [1,2,3,3,3,4,5,5,6]
    =3D> [1, 2, 3, 3, 3, 4, 5, 5, 6]

    b =3D [3,4,5]
    =3D> [3, 4, 5]

    a.subtract b
    =3D> [1, 2, 3, 3, 5, 6]

    a
    =3D> [1, 2, 3, 3, 5, 6]


    -Adam
     
    Adam Shelly, Feb 5, 2006
    #15
  16. Dave Howell wrote:
    > I thought I was actually going to enter my first RubyQuiz, but I've
    > spent three times as much time trying to get Ruby to stop surprising me
    > as I have trying to implement my algorithm, and I've had to abandon my
    > effort since I don't have the time to spend. Sigh.
    >
    > Can somebody explain to me how I'm supposed to delete a *single*
    > element from an array based on equivalence with an object? and get back
    > said array with said element deleted?
    >
    > In other words....
    >
    > ar = [1, 2, 3, 8, 15, 15, 8]
    >
    > ar.delete_one_element!(15)
    > => [1, 2, 3, 8, 15, 8]
    >
    > ar.delete_one_element!(14)
    > => [1, 2, 3, 8, 15, 15, 8]
    >
    > ar.delete_one_element!(nil)
    > => [1, 2, 3, 8, 15, 15, 8]
    >
    > I did find so many different ways of not doing this....
    >
    > Too enthusiastic....
    > ar.delete(15)
    > => 15
    > ar
    > => [1, 2, 3, 8, 8]
    >
    > Right results, wrong output...
    > ar.slice!(ar.index(15))
    > => 15
    > ar
    > => [1, 2, 3, 8, 15, 8]
    >
    > and also surprised me by not handling 'nil' as I wanted...
    > ar.slice!(ar.index(13))
    > TypeError: no implicit conversion from nil to integer
    > from (irb):8:in `slice!'
    > from (irb):8
    >
    >
    > I mean, this seems so, er, obvious! "Please find one instance of this
    > object in the array, and return to me the array without that object. If
    > the array doesn't have that object, then just give the array back to
    > me."


    This may not be of any use to you, but here's a way to delete all
    elements but the first:

    class Array
    def no_dup!( x )
    (i = index(x)) && delete( x ) && insert(i,x)
    self
    end
    end

    And here's another version of delete_one_element!.

    class Array
    def delete_one_element!( x )
    (i = index(x)) && delete_at( i )
    self
    end
    end
     
    William James, Feb 5, 2006
    #16
  17. wrote:

    > [...]
    > not raising an error when the element is not found is an
    > amazingly bad idea that would mask many bugs
    > [...]


    Well, i don't think it's 'amazingly bad'. Array#- doesn't raise an error
    in this case, Array#clear doesn't raise an error if the array is already
    empty, neither does the Array intersection or any of the Set methods.

    Perhaps you can explain why Array#delete doesn't return the array but
    the parameter (preventing method chaining).

    My first idea was that it should work like Array#flatten /
    Array#flatten! both returning the modified array, the bang version
    returning nil if there was no modification.

    Ok, just my 2 cents, fell free to ignore this post - i just stumbled
    about a similar 'inconsistency' myself and wanted to say that.
    (no i don't want to change ruby, and there is no offense intended)

    cheers

    Simon
     
    Simon Kröger, Feb 5, 2006
    #17
  18. --------------000301040205060500080400
    Content-Type: text/plain; charset=ISO-8859-1; format=flowed
    Content-Transfer-Encoding: 7bit

    William James wrote:
    > Dave Howell wrote:
    >
    >> I thought I was actually going to enter my first RubyQuiz, but I've
    >> spent three times as much time trying to get Ruby to stop surprising me
    >> as I have trying to implement my algorithm, and I've had to abandon my
    >> effort since I don't have the time to spend. Sigh.
    >>
    >> Can somebody explain to me how I'm supposed to delete a *single*
    >> element from an array based on equivalence with an object? and get back
    >> said array with said element deleted?
    >>
    >> In other words....
    >>
    >> ar = [1, 2, 3, 8, 15, 15, 8]
    >>
    >> ar.delete_one_element!(15)
    >> => [1, 2, 3, 8, 15, 8]
    >>
    >> ar.delete_one_element!(14)
    >> => [1, 2, 3, 8, 15, 15, 8]
    >>
    >> ar.delete_one_element!(nil)
    >> => [1, 2, 3, 8, 15, 15, 8]
    >>
    >> I did find so many different ways of not doing this....
    >>
    >> Too enthusiastic....
    >> ar.delete(15)
    >> => 15
    >> ar
    >> => [1, 2, 3, 8, 8]
    >>
    >> Right results, wrong output...
    >> ar.slice!(ar.index(15))
    >> => 15
    >> ar
    >> => [1, 2, 3, 8, 15, 8]
    >>
    >> and also surprised me by not handling 'nil' as I wanted...
    >> ar.slice!(ar.index(13))
    >> TypeError: no implicit conversion from nil to integer
    >> from (irb):8:in `slice!'
    >> from (irb):8
    >>
    >>
    >> I mean, this seems so, er, obvious! "Please find one instance of this
    >> object in the array, and return to me the array without that object. If
    >> the array doesn't have that object, then just give the array back to
    >> me."
    >>

    >
    > This may not be of any use to you, but here's a way to delete all
    > elements but the first:
    >
    > class Array
    > def no_dup!( x )
    > (i = index(x)) && delete( x ) && insert(i,x)
    > self
    > end
    > end
    >
    > And here's another version of delete_one_element!.
    >
    > class Array
    > def delete_one_element!( x )
    > (i = index(x)) && delete_at( i )
    > self
    > end
    > end
    >
    >
    >
    >

    And here's yet another version, similar to the ones already posted though:

    class Array
    def delete_one! n
    (i = index(n)) ? delete_at(i) : nil
    end
    end

    --------------000301040205060500080400--
     
    Patrick Deuster, Feb 5, 2006
    #18
  19. On Feb 5, 2006, at 5:28 AM, William James wrote:

    > This may not be of any use to you, but here's a way to delete all
    > elements but the first:
    >
    > class Array
    > def no_dup!( x )
    > (i = index(x)) && delete( x ) && insert(i,x)
    > self
    > end
    > end


    Array.uniq!

    ???

    James Edward Gray II
     
    James Edward Gray II, Feb 5, 2006
    #19
  20. Dave Howell

    Guest

    On Sun, 5 Feb 2006, [ISO-8859-1] Simon Kr=F6ger wrote:

    > wrote:
    >
    >> [...]
    >> not raising an error when the element is not found is an
    >> amazingly bad idea that would mask many bugs
    >> [...]

    >
    > Well, i don't think it's 'amazingly bad'. Array#- doesn't raise an error =

    in
    > this case, Array#clear doesn't raise an error if the array is already emp=

    ty,
    > neither does the Array intersection or any of the Set methods.
    >
    > Perhaps you can explain why Array#delete doesn't return the array but the
    > parameter (preventing method chaining).
    >
    > My first idea was that it should work like Array#flatten / Array#flatten!
    > both returning the modified array, the bang version returning nil if ther=

    e
    > was no modification.
    >
    > Ok, just my 2 cents, fell free to ignore this post - i just stumbled abou=

    t a
    > similar 'inconsistency' myself and wanted to say that. (no i don't want =

    to
    > change ruby, and there is no offense intended)
    >
    > cheers


    good points all. i can only guess

    - Array#- doesn't raise an error since it can partially succeed/fail, in
    otherwords some of the elements might be removed while some are not: i=
    s
    this success or failure? also Array#- is defined as 'set difference' =
    and,
    under that def not raising an error certainly makes good sense - the
    result is always what you asked for - even if it's empty.

    - Array#clear shouldn't raise an error, since the result after calling i=
    t
    always want you'd hoped for : an empty arrray.

    - Array#delete... well you got me there. nil is at least useful so one =
    can
    do

    a.delete(elem) or raise "failed"

    otherwise you have no idea if the operation succeeded or not.


    the thing with writing a Array#delete_first method that returns the array i=
    s
    that there's absolutely no indication of success or, as in the case of
    Array#clear, a guarantee of success.

    in general i think methods basically fail into two categories

    - those that always succeed, Array#clear for example. these can simply
    return self.

    - those that might fail and need to either return nil or raise an except=
    ion
    to indicate this. raising is nice because you can chain.

    it's not clear to me why 'delete_first' would be in the first category but =
    i
    think this is largely religious.

    cheers.

    -a

    --=20
    happiness is not something ready-made. it comes from your own actions.
    - h.h. the 14th dali lama
     
    , Feb 5, 2006
    #20
    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. Ruby Quiz

    [QUIZ] Animal Quiz (#15)

    Ruby Quiz, Jan 14, 2005, in forum: Ruby
    Replies:
    11
    Views:
    433
    James Edward Gray II
    Jan 18, 2005
  2. globalrev
    Replies:
    4
    Views:
    116
    Marc Heiler
    May 10, 2008
  3. Eric I.
    Replies:
    0
    Views:
    289
    Eric I.
    Oct 5, 2008
  4. Einar Boson
    Replies:
    6
    Views:
    204
    Rick DeNatale
    Feb 2, 2009
  5. matt neuburg
    Replies:
    1
    Views:
    116
    Rick DeNatale
    Feb 17, 2009
Loading...

Share This Page