2011-12-20 33 views
33

Hãy xem xét mã sau:Các chuỗi trong Ruby có thể thay đổi được không?

$ irb 
> s = "asd" 
> s.object_id # prints 2171223360 
> s[0] = ?z  # s is now "zsd" 
> s.object_id # prints 2171223360 (same as before) 
> s += "hello" # s is now "zsdhello" 
> s.object_id # prints 2171224560 (now it's different) 

Có vẻ như các ký tự riêng lẻ có thể được thay đổi bằng cách tạo chuỗi mới. Tuy nhiên phụ thêm vào chuỗi dường như tạo ra một chuỗi mới.

Các chuỗi trong Ruby có thể thay đổi không?

+2

Có, và có thể trả lời thông qua tìm kiếm tầm thường. http://stackoverflow.com/questions/2608493/why-did-matz-choose-to-make-strings-mutable-by-default-in-ruby –

+0

@DaveNewton: Nó tuyệt vời không dễ dàng như thế nào để tìm dups trên SO như bạn gần như có thể đếm trên một chủ đề SO sắp tới đầu tiên trên google? –

+4

'+' là ghép nối và sẽ trả về một chuỗi mới. '<<' được thêm vào và sẽ gắn thêm vào đối tượng chuỗi đã cho (không tạo đối tượng chuỗi mới). – Chad

Trả lời

37

Có, chuỗi trong Ruby, không giống như trong Python, có thể thay đổi.

s += "hello"không thêm "hello" to s - đối tượng chuỗi hoàn toàn mới được tạo. Để thêm vào sau một chuỗi 'tại chỗ', sử dụng <<, như trong:

s = "hello" 
s << " world" 
s # hello world 
+3

Bạn có nghĩ rằng 'a + = b' là' a = a + b' trong Ruby không? Điều đó sẽ làm cho nó rõ ràng tại sao 's + =" hello "' tạo ra một chuỗi mới. – emlai

+1

@tuple_cat Vâng, đó là cách '+ =' được thực hiện, do đó xác định lại '+' sản lượng được xác định lại '+ ='. – YoTengoUnLCD

8

Phụ thêm trong Ruby String không phải là +=, nó là <<

Vì vậy, nếu bạn thay đổi += để << câu hỏi của bạn được giải quyết bằng cách riêng của mình

+3

+1. Như được giải thích tại http://www.rubyfleebie.com/appending-to-a-string/, "' + = 'sẽ tạo một thể hiện String mới và gán nó cho đối tượng bên trái của bạn. Mặt khác,' << 'sẽ nối chuỗi mới trực tiếp vào đối tượng bên trái đã tồn tại của bạn." – ruakh

11
ruby-1.9.3-p0 :026 > s="foo" 
=> "foo" 
ruby-1.9.3-p0 :027 > s.object_id 
=> 70120944881780 
ruby-1.9.3-p0 :028 > s<<"bar" 
=> "foobar" 
ruby-1.9.3-p0 :029 > s.object_id 
=> 70120944881780 
ruby-1.9.3-p0 :031 > s+="xxx" 
=> "foobarxxx" 
ruby-1.9.3-p0 :032 > s.object_id 
=> 70120961479860 

vậy, Strings là có thể thay đổi, nhưng += điều hành tạo ra một Chuỗi mới. << giữ cũ

6

Strings trong Ruby là có thể thay đổi, nhưng bạn có thể thay đổi nó với đóng băng.

irb(main):001:0> s = "foo".freeze 
=> "foo" 
irb(main):002:0> s << "bar" 
RuntimeError: can't modify frozen String 
0

Từ những gì tôi có thể làm cho các this pull request, nó sẽ trở thành có thể trong Ruby 3.0 để thêm một "bình luận kỳ diệu" sẽ làm cho tất cả các chuỗi bất biến, chứ không phải là có thể thay đổi.

Vì có vẻ như bạn phải thêm nhận xét này một cách rõ ràng, có vẻ như câu trả lời cho "là chuỗi có thể thay đổi theo mặc định?" vẫn sẽ có, nhưng một loại điều kiện có - phụ thuộc vào việc bạn đã viết nhận xét ma thuật vào kịch bản của bạn hay không.

EDIT

tôi đã chỉ vào bug/issue on Ruby-Lang.org này mà dứt khoát khẳng định rằng một số loại chuỗi trong Ruby 3.0 sẽ trên thực tế không thay đổi theo mặc định.

1

Chuỗi Ruby có thể thay đổi. Nhưng bạn cần sử dụng < < để ghép nối thay vì +.
Trong thực tế chuỗi nối với
+ toán tử (không thay đổi) vì nó tạo đối tượng chuỗi mới.
< < toán tử (có thể thay đổi) vì thay đổi trong cùng một đối tượng.

Các vấn đề liên quan