Keep changes in string outside of scope?

The code below is supposed to scan through a string and put a ',' before all zip codes. The code properly detects the zip codes and makes the change in x but the change is never reflected in thestring. How can I get these changes to exist outside of x's scope?

thestring.each do |x|
    if x =~ /\d{5}/
      puts "match"
      x[-6] = ","
      puts x
  end
end

Thank you,
Matthew Margolis

What about:

thestring.gsub!(/(\d{5})/, '\1')

That help?

James Edward Gray II

···

On Sep 27, 2004, at 4:39 PM, Matthew Margolis wrote:

The code below is supposed to scan through a string and put a ',' before all zip codes. The code properly detects the zip codes and makes the change in x but the change is never reflected in thestring. How can I get these changes to exist outside of x's scope?

thestring.each do |x|
   if x =~ /\d{5}/
     puts "match"
     x[-6] = ","
     puts x
end
end

Hi --

···

On Tue, 28 Sep 2004, Matthew Margolis wrote:

The code below is supposed to scan through a string and put a ','
before all zip codes. The code properly detects the zip codes and makes
the change in x but the change is never reflected in thestring. How can
I get these changes to exist outside of x's scope?

thestring.each do |x|
    if x =~ /\d{5}/
      puts "match"
      x[-6] = ","
      puts x
  end
end

The thing is, each substring, as returned by #each, is a new object,
so nothing you do to them affects the original string. You could
probably achieve what you want with:

  thestring.sub!(/\d{5}/) {|x| "#{x},"}

David

--
David A. Black
dblack@wobblini.net

Hi --

···

On Tue, 28 Sep 2004, David A. Black wrote:

  thestring.sub!(/\d{5}/) {|x| "#{x},"}

Amendment: as James G. suggested, use gsub! if you have more than one
in one string :slight_smile: Also make sure that you have no street numbers with
five digits in a row.

David

--
David A. Black
dblack@wobblini.net

What about:

thestring.gsub!(/(\d{5})/, '\1')

Oops, forgot the period. The replace string should be '.\1'. Sorry

James Edward Gray II

···

That help?

James Edward Gray II

David A. Black wrote:

Hi --

thestring.sub!(/\d{5}/) {|x| "#{x},"}
   
Amendment: as James G. suggested, use gsub! if you have more than one
in one string :slight_smile: Also make sure that you have no street numbers with
five digits in a row.

David

Excellent. I didn't know that each returned new objects. Thanks a bunch guys.

-Matt Margolis

···

On Tue, 28 Sep 2004, David A. Black wrote:

"James Edward Gray II" <james@grayproductions.net> schrieb im Newsbeitrag
news:CFC5333A-10CF-11D9-8CFB-000A95BA45F8@grayproductions.net...

> What about:
>
> thestring.gsub!(/(\d{5})/, '\1')

Oops, forgot the period. The replace string should be '.\1'. Sorry

He wanted a comma...
:slight_smile:

And without diving too far into escape handling I'd use

thestring.gsub!(/\d{5}/, ',\\&')

Note also, that you don't need the grouping.

    robert

"David A. Black" <dblack@wobblini.net> schrieb im Newsbeitrag
news:Pine.LNX.4.44.0409271452500.8281-100000@wobblini...

Hi --

> thestring.sub!(/\d{5}/) {|x| "#{x},"}

Amendment: as James G. suggested, use gsub! if you have more than one
in one string :slight_smile: Also make sure that you have no street numbers with
five digits in a row.

The block variant isn't necessary in this case. A remark about
efficiency:

require 'benchmark'

REP = 1000

thestring = ("foo 12345 bar baz" * 100).freeze

Benchmark.bm(15) do |b|
  b.report "direct" do
    REP.times { thestring.gsub(/\d{5}/, ',\\&') }
  end

  b.report "direct group" do
    REP.times { thestring.gsub(/(\d{5})/, ',\\1') }
  end

  b.report "block" do
    REP.times { thestring.gsub(/\d{5}/) {|m| ",#{m}"} }
  end
end

                     user system total real
direct 0.516000 0.000000 0.516000 ( 0.527000)
direct group 0.546000 0.000000 0.546000 ( 0.537000)
block 1.829000 0.000000 1.829000 ( 1.844000)

Kind regards

    robert

···

On Tue, 28 Sep 2004, David A. Black wrote:

Hi --

···

On Tue, 28 Sep 2004, Matthew Margolis wrote:

David A. Black wrote:

>Hi --
>
>On Tue, 28 Sep 2004, David A. Black wrote:
>
>
>
>> thestring.sub!(/\d{5}/) {|x| "#{x},"}
>>
>>
>
>Amendment: as James G. suggested, use gsub! if you have more than one
>in one string :slight_smile: Also make sure that you have no street numbers with
>five digits in a row.
>
>
>David
>
>
>
Excellent. I didn't know that each returned new objects. Thanks a
bunch guys.

Just to clarify: it (each) doesn't always return new objects; it
depends on the particular case. For example, in the case of
Array#each, you do get the actual array element. With strings, the
effect is like splitting the string into lines, i.e., substrings.

David

--
David A. Black
dblack@wobblini.net

David A. Black wrote:

Hi --

David A. Black wrote:

Hi --

thestring.sub!(/\d{5}/) {|x| "#{x},"}
  

Amendment: as James G. suggested, use gsub! if you have more than one
in one string :slight_smile: Also make sure that you have no street numbers with
five digits in a row.

David

Excellent. I didn't know that each returned new objects. Thanks a bunch guys.
   
Just to clarify: it (each) doesn't always return new objects; it
depends on the particular case. For example, in the case of
Array#each, you do get the actual array element. With strings, the
effect is like splitting the string into lines, i.e., substrings.

David

Understood.

-Matt Margolis

···

On Tue, 28 Sep 2004, Matthew Margolis wrote:

On Tue, 28 Sep 2004, David A. Black wrote: