Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Quiz #65, Principle of Great Surprise, and Array.delete sledgehammer

Reply
Thread Tools

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

 
 
Dave Howell
Guest
Posts: n/a
 
      02-04-2006
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?





 
Reply With Quote
 
 
 
 
Levin Alexander
Guest
Posts: n/a
 
      02-04-2006
T24gMi80LzA2LCBEYXZlIEhvd2VsbCA8Z3JvdXBzQGdyYW5kZm Vud2ljay5uZXQ+IHdyb3RlOgo+
IEkgbWVhbiwgdGhpcyBzZWVtcyBzbywgZXIsIG9idmlvdXMhIC JQbGVhc2UgZmluZCBvbmUgaW5z
dGFuY2Ugb2YgdGhpcwo+IG9iamVjdCBpbiB0aGUgYXJyYXksIG FuZCByZXR1cm4gdG8gbWUgdGhl
IGFycmF5IHdpdGhvdXQgdGhhdCBvYmplY3QuIElmCj4gdGhlIG FycmF5IGRvZXNuJ3QgaGF2ZSB0
aGF0IG9iamVjdCwgdGhlbiBqdXN0IGdpdmUgdGhlIGFycmF5IG JhY2sgdG8KPiBtZS4iCgogIGNs
YXNzIEFycmF5CiAgICBkZWYgd2l0aG91dF9vbmUoZWxlbSkKIC AgICAgbmV3ID0gc2VsZi5kdXAg
IyBtYWtlIGEgY29weSBzbyB0aGF0IHRoZSBvcmlnaW5hbCBpcy Bub3QgY2hhbmdlZAogICAgICBu
ZXcuZGVsZXRlX2F0KG5ldy5pbmRleChlbGVtKSkKICAgICAgbm V3CiAgICBlbmQKICBlbmQKCiAg
WzEsMiwzLDQsNCw0LDUsNV0ud2l0aG91dF9vbmUoNCkgIz0+IF sxLDIsMyw0LDQsNSw1XQoKLUxl
dmluCg==


 
Reply With Quote
 
 
 
 
James Edward Gray II
Guest
Posts: n/a
 
      02-04-2006
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


 
Reply With Quote
 
ara.t.howard@noaa.gov
Guest
Posts: n/a
 
      02-04-2006
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


 
Reply With Quote
 
Logan Capaldo
Guest
Posts: n/a
 
      02-04-2006

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[i]) }
unless index_of_element.nil?
self.delete_at(index_of_element)
end
self
end
end





 
Reply With Quote
 
Levin Alexander
Guest
Posts: n/a
 
      02-04-2006
T24gMi80LzA2LCBXaWxzb24gQmlsa292aWNoIDx3aWxzb25iQG dtYWlsLmNvbT4gd3JvdGU6Cj4g
T24gMi80LzA2LCBEYXZlIEhvd2VsbCA8Z3JvdXBzQGdyYW5kZm Vud2ljay5uZXQ+IHdyb3RlOgo+
Cj4gU29tZW9uZSB3aWxsIHByb2JhYmx5IHBvc3QgYSBzb2x1dG lvbiB0aGF0IHVzZXMgaW5qZWN0
LCB0aG91Z2guIEhlaC4KCmNsYXNzIEVudW1lcmFibGUKICBkZW YgZGVsZXRlX29uZV9vZihvYmop
CiAgICBzZWxmLmluamVjdChbXSxmYWxzZSkgeyB8KGFyciwgYW xyZWFkeV9kZWxldGVkKSwgZWxl
bXwKICAgICAgYXJyIDw8IGVsZW0gdW5sZXNzIGVsZW0gPT0gb2 JqIGFuZCBub3QgYWxyZWFkeV9k
ZWxldGVkCiAgICAgIGFscmVhZHlfZGVsZXRlZCA9IHRydWUgaW YgZWxlbSA9PSBvYmoKICAgICAg
W2FyciwgYWxyZWFkeV9kZWxldGVkXQogICAgfVswXQogIGVuZA plbmQKCi4uLiB0aGlzIGlzIHVu
dGVzdGVkCgotTGV2aW4sIHNjbnIK


 
Reply With Quote
 
Simon Kröger
Guest
Posts: n/a
 
      02-04-2006

> 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


 
Reply With Quote
 
Dave Howell
Guest
Posts: n/a
 
      02-04-2006

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.





 
Reply With Quote
 
Dave Howell
Guest
Posts: n/a
 
      02-04-2006

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



 
Reply With Quote
 
Joel VanderWerf
Guest
Posts: n/a
 
      02-04-2006
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


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
rescue and principle of least surprise matt neuburg Ruby 1 02-17-2009 01:12 PM
Conventions in ruby and the principle of least surprise Einar Boson Ruby 6 02-02-2009 04:44 PM
[QUIZ] 1-800-THE-QUIZ (#20) Ruby Quiz Ruby 15 02-24-2005 06:05 AM
[SOLUTION] Ruby Quiz #15 Animal Quiz David Tran Ruby 9 01-21-2005 02:11 AM
[QUIZ] Animal Quiz (#15) Ruby Quiz Ruby 11 01-18-2005 02:42 PM



Advertisments