[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

first and last char

botp

8/11/2007 5:30:00 PM

I always get tripped when working together w arrays and strings specially on,

string.first and string.last

of course, they err :)

wish there were #first and #last in String

just a thought
kind regards -botp

11 Answers

Stefan Rusterholz

8/11/2007 7:35:00 PM

0

Felix Windt wrote:
>>
>> of course, they err :)
>>
>> wish there were #first and #last in String
>>
>> just a thought
>> kind regards -botp
>>
>
> irb(main):001:0> class String
> irb(main):002:1> def first
> irb(main):003:2> self.split('').first
> irb(main):004:2> end
> irb(main):005:1> def last
> irb(main):006:2> self.split('').last
> irb(main):007:2> end
> irb(main):008:1> end
> => nil
> irb(main):009:0> "testing".first
> => "t"
> irb(main):010:0> "testing".last
> => "g"

Ew, that's awfully complex. You create n new objects from which you
throw n-1 away again...
Think of the memory! ;-)
def first; self[0,1]; end; def last; self[-1,1]; end

Regards
Stefan
--
Posted via http://www.ruby-....

Daniel DeLorme

8/12/2007 1:53:00 AM

0

Stefan Rusterholz wrote:
> Ew, that's awfully complex. You create n new objects from which you
> throw n-1 away again...
> Think of the memory! ;-)
> def first; self[0,1]; end; def last; self[-1,1]; end

wrong, that's the first and last *bytes*, not characters.

def first; self[/\A./m]; end
def last; self[/.\z/m]; end

>> $KCODE='u'
=> "u"
>> "���".first
=> "æ?¥"
>> "���".last
=> "�"

Daniel

Stefan Rusterholz

8/12/2007 10:07:00 AM

0

Daniel DeLorme wrote:
> Stefan Rusterholz wrote:
>> Ew, that's awfully complex. You create n new objects from which you
>> throw n-1 away again...
>> Think of the memory! ;-)
>> def first; self[0,1]; end; def last; self[-1,1]; end
>
> wrong, that's the first and last *bytes*, not characters.
>
> def first; self[/\A./m]; end
> def last; self[/.\z/m]; end
>
> >> $KCODE='u'
> => "u"
> >> "���".first
> => "æ?¥"
> >> "���".last
> => "�"
>
> Daniel

You are right, your solution is better.

Regards
Stefan
--
Posted via http://www.ruby-....

Daniel DeLorme

8/12/2007 1:28:00 PM

0

Stefan Rusterholz wrote:
> Daniel DeLorme wrote:
>> def first; self[/\A./m]; end
>> def last; self[/.\z/m]; end
>>
>> >> $KCODE='u'
>> => "u"
>> >> "���".first
>> => "æ?¥"
>> >> "���".last
>> => "�"
>>
>> Daniel
>
> You are right, your solution is better.

Only partly. Unfortunately, end-anchored regular expressions have pretty
abysmal performance.

>> require "benchmark"
>> str = "���"*1000
>> Benchmark.measure{10000.times{str.first}}.real
=> 0.0704410076141357
>> Benchmark.measure{10000.times{str.last}}.real
=> 5.35788202285767

:-(
Daniel

Trans

8/12/2007 2:31:00 PM

0



On Aug 11, 6:52 pm, Daniel DeLorme <dan...@dan42.com> wrote:
> Stefan Rusterholz wrote:
> > Ew, that's awfully complex. You create n new objects from which you
> > throw n-1 away again...
> > Think of the memory! ;-)
> > def first; self[0,1]; end; def last; self[-1,1]; end
>
> wrong, that's the first and last *bytes*, not characters.

For Ruby 1.9+ it will just be:

def first; self[0]; end; def last; self[-1]; end


my own version is (basically):

def first(pattern=//)
split(pattern).at(0)
end

which is a little more versatile. but I see the point about the
memory, and I'll add an optimization clause come 1.9.

T.


Stefan Rusterholz

8/12/2007 10:10:00 PM

0

Daniel DeLorme wrote:
> Stefan Rusterholz wrote:
>>>
>>> Daniel
>>
>> You are right, your solution is better.
>
> Only partly. Unfortunately, end-anchored regular expressions have pretty
> abysmal performance.
>
> >> require "benchmark"
> >> str = "���"*1000
> >> Benchmark.measure{10000.times{str.first}}.real
> => 0.0704410076141357
> >> Benchmark.measure{10000.times{str.last}}.real
> => 5.35788202285767
>
> :-(
> Daniel

That can be helped. Assuming that there is no encoding with 1 char > 8
bytes:

def first; self[/\A./m]; end
def last; self[/.\z/m]; end
def last2; self[-8,8][/.\z/m]; end

Benchmark.measure{10000.times{str.first}}.real
=> 0.0643939971923828
Benchmark.measure{10000.times{str.last}}.real
=> 7.3151650428772
Benchmark.measure{10000.times{str.last2}}.real
=> 0.167464017868042

That's a 40x improvement for that string. For short strings it will
probably be slightly slower, but I'd say it's worth it.

Regards
Stefan
--
Posted via http://www.ruby-....

Bertram Scharpf

8/13/2007 6:04:00 AM

0

Hi,

Am Sonntag, 12. Aug 2007, 02:43:00 +0900 schrieb Felix Windt:
> > -----Original Message-----
> > From: botp [mailto:botpena@gmail.com]
> > Sent: Saturday, August 11, 2007 10:30 AM
> >
> > wish there were #first and #last in String
>
> irb(main):001:0> class String
> irb(main):002:1> def first
> irb(main):003:2> self.split('').first
> irb(main):004:2> end
> irb(main):005:1> def last
> irb(main):006:2> self.split('').last
> irb(main):007:2> end
> irb(main):008:1> end
> => nil
> irb(main):009:0> "testing".first
> => "t"
> irb(main):010:0> "testing".last
> => "g"

Sometimes I wish every young programmer was forced to do a
month in Assembler and another one in C just to see what
cost in time and space some constructions cause.

Sorry, Felix!

Bertram


--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-...

Stephan Kämper

8/13/2007 6:16:00 AM

0

Hi,

Am 13.08.2007 um 08:04 schrieb Bertram Scharpf:
> Hi,
>
> Am Sonntag, 12. Aug 2007, 02:43:00 +0900 schrieb Felix Windt:
>>> -----Original Message-----
>>> From: botp [mailto:botpena@gmail.com]
>>> Sent: Saturday, August 11, 2007 10:30 AM
>>>
>>> wish there were #first and #last in String
>>
>> irb(main):001:0> class String
>> irb(main):002:1> def first
>> irb(main):003:2> self.split('').first
>> irb(main):004:2> end
>> irb(main):005:1> def last
>> irb(main):006:2> self.split('').last
>> irb(main):007:2> end
>> irb(main):008:1> end
>> => nil
>> irb(main):009:0> "testing".first
>> => "t"
>> irb(main):010:0> "testing".last
>> => "g"
>
> Sometimes I wish every young programmer was forced to do a
> month in Assembler and another one in C just to see what
> cost in time and space some constructions cause.
>
> Sorry, Felix!

Well, here's something that should be a little bit less cycle
intensive (depending on how String#[](arg) is implemented):

class String
def last
self[-1].chr
end
end

Cheers


Stephan


--
Stephan Kämper/IT-Beratung http://www.stephan...
Softwaretest / Datenanalyse / Entwicklung



Bertram Scharpf

8/13/2007 7:06:00 AM

0

Hi,

Am Montag, 13. Aug 2007, 15:15:54 +0900 schrieb Stephan Kämper:
> Am 13.08.2007 um 08:04 schrieb Bertram Scharpf:
>
> Well, here's something that should be a little bit less cycle intensive
> (depending on how String#[](arg) is implemented):
>
> class String
> def last
> self[-1].chr
> end
> end

This is what I would have implemented, too.

The difficult point is that it raises some questions:

- Should it return a Fixnum or a String of lenght 1?
- Should it be able to return UTF-8 characters?
- Should I define String#shift and String#pop now?

I don't recommend to discuss such question in an open forum
since I saw what happened to my String#notempty? proposal.

Bertram

--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-...

Trans

8/13/2007 12:25:00 PM

0



On Aug 13, 12:06 am, Bertram Scharpf <li...@bertram-scharpf.de> wrote:

> I don't recommend to discuss such question in an open forum
> since I saw what happened to my String#notempty? proposal.

Sad for Ruby.

T.