Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does string replace modifies the original variable value?

9.3 I'm getting a strange behaviour and I cannot understand why:

s = self.shopify_p
s.title
=> "Disco (Wholesale)"

Right now I'd like to have a new variable with the content of s.title without the " (Wholesale)" part. So I do the following:

original_title = s.title
=> "Disco (Wholesale)" 
original_title[" (Wholesale)"] = ""
=> ""

Now if I do:

original_title
=> "Disco"

Which is ok but the strange thing is that it seems that the last string replace affected even the original s variable:

s.title
=> "Disco"

I really cannot understand this...can you tell me what is happening here?

s.title should still be "Disco (Wholesale)"...or not?

like image 313
Augusto Avatar asked Jul 13 '12 12:07

Augusto


People also ask

What happens when string value is changed?

Value of the StringValue is changed. It will run with the new value being stored in the argument object, instead of a string representing the property being changed. This event, like other changed events, can be used to track when an StringValue changes and to track the different values that it may change to.

Does a string variable change after applying a method?

Unless you assign the variable to be itself with a string method modifying it, then it will remain the same.

What is string replace in JavaScript?

The replace() method searches a string for a value or a regular expression. The replace() method returns a new string with the value(s) replaced. The replace() method does not change the original string.

Does Java Replaceall modify original string?

Strings in Java are immutable - when you call replace , it doesn't change the contents of the existing string - it returns a new string with the modifications.


3 Answers

It is the same because you're accessing the same object.

irb(main):006:0> x = "aaaa"
=> "aaaa"
irb(main):007:0> y = x 
=> "aaaa"
irb(main):008:0> x.object_id 
=> 70358166435920
irb(main):009:0> y.object_id
=> 70358166435920
irb(main):010:0> 

What you could do instead is

original_title = s.title.gsub(" (Wholesale)","")
like image 54
vvlad Avatar answered Sep 27 '22 17:09

vvlad


After original_title = s.title both original_title and s.title reference the same object.

To actually copy the string either use Object#dup:

original_title = s.title.dup

dup → an_object

Produces a shallow copy of obj

or String.new:

original_title = String.new(s.title)

new(str="") → new_str

Returns a new string object containing a copy of str.

like image 29
Stefan Avatar answered Sep 27 '22 17:09

Stefan


Variables in ruby reference the objects they point to rather than copying them by default. So, if you change the underlying object, any changes will show up in any variables that contain a reference to that object.

If a, b, c and d all point to the same object, changes to any will "change" (be visible through) all of them.

  a  b  c
   \ | /
   Object
     |
     d

If you want to keep your original value you'll need to somehow create a new variable.

irb(main):001:0> a = "Foo"
=> "Foo"
irb(main):002:0> b = a
=> "Foo"
irb(main):003:0> a << " Bar"
=> "Foo Bar"
irb(main):004:0> b
=> "Foo Bar"
irb(main):005:0> a
=> "Foo Bar"
irb(main):006:0> a += " Baz"
=> "Foo Bar Baz"
irb(main):007:0> a
=> "Foo Bar Baz"
irb(main):008:0> b
=> "Foo Bar"

For your case @wlad's gsub (note that he didn't use gsub!) suggestion seems like a good one.

original_title = s.title.gsub(" (Wholesale)","")
like image 27
Paul Rubel Avatar answered Sep 27 '22 18:09

Paul Rubel