> -----Original Message-----
> From: list-bounce / example.com
> [mailto:list-bounce / example.com] On Behalf Of Jeff Pritchard
> Sent: Wednesday, June 28, 2006 8:52 AM
> To: ruby-talk ML
> Subject: Re: string manipulation
>
> I really like Alex's solution to this.  As a newbie, I always attempt
> these "easy" things just to help me learn more of the
> language.

I've not been programming ruby for long, so these nasty oneliners amuse me
greatly, as well.

> My solution involved reversing the string as Alex did, and
> then trying
> to use "each_with_index" on it to iterate through the
> characters.

The biggest problem I had with the String#each or String#each_with_index
approach is that you don't get a string out of it at the end, you get an
array. This means you need to operate directly on the string inside your
block, which may or may not be pretty.

> Also, my first thought on a solution for this was to simply
> walk along
> the string and insert dashes where appropriate. Why isn't there a
> "String#insert(where,str)" method?  Inserting substrings into strings
> seems like such a common thing to do.

As someone else pointed out, String#insert does exist. For the given string
you can do:

[2,7,12,17].inject("123456789123456789") {|string, index|
string.insert(index,'-')}

Which is quite nice, and shows off inject, which is AWESOME.

Sadly, to call it a real oneliner you'd need to construct that initial
array, which I was unable to do in a manner I consider fit for print.
Another way to attack the same thing, though, would be with Range#step:

(2..str.length-1).step(5) {|index| str.insert(index,'-')}

Which is also not ugly, but check the way it handles cases that have
different lengths to the OP's string - the /..../ double reverse, the regexp
and the 'insert at index' approaches all behave different ways; not all of
which are likely "correct".

> Can someone offer some clarification?

I think you should look again at Paul Battley's approach, which is (IMVHO)
actually the most readable and elegant approach, once you take out the
redundant passive grouping (as done here):

str.gsub(/^\d{2}|\d{4}(?=.)/, '\0-')

Once deconstructed, it's looking for start followed by two numbers, OR any
four numbers, provided they are followed by another character (you could
also write (?!$) for not end-of-line). If it finds one of those it appends a
dash. Personally, I could look at this solution and say what it is supposed
to do without running it (and without bending my brain). Only the explicit
inject example above rings my readability meter as loudly.

> thanks,
> jp

Cheers,

ben