Làm thế nào để xóa các ký tự cụ thể khỏi một chuỗi trong Ruby?


82

Tôi có một số chuỗi trông như thế này:

"((String1))"

Chúng đều có độ dài khác nhau. Làm cách nào tôi có thể xóa dấu ngoặc đơn khỏi tất cả các chuỗi này trong một vòng lặp?


2
Xóa dấu ngoặc đơn hoặc xóa hai ký tự đầu tiên và hai ký tự cuối cùng khỏi chuỗi "ngẫu nhiên"? (Thực ra là ngẫu nhiên?)
Phục hồi Monica - notmaynard

"((Chuỗi1))" [2 ...- 2] # => "Chuỗi1"
Khôi phục Monica - notmaynard


Bạn đang hỏi một vòng lặp để thay đổi nhiều chuỗi, các chuỗi được lưu trữ như thế nào?
hirolau

Tôi biết cách tạo một vòng lặp qua tất cả các chuỗi mà tôi chỉ muốn phần thao tác chuỗi, xin lỗi vì tôi đã nói điều đó thật kỳ lạ
Cristiano

Câu trả lời:


165

Làm như bên dưới bằng cách sử dụng String#tr:

 "((String1))".tr('()', '')
 # => "String1"

7
Ngoài ra còn có một phiên bản phá hủy tr!sẽ sửa đổi một chuỗi tại chỗ, nhưmy_string.tr!(')(','')
bonh

8
Lưu ý rằng hàm này không phải là cắt bớt từ đầu hoặc cuối, mà là một sự thay thế đầy đủ trên tất cả văn bản trong chuỗi.
Jordan

3
Gây hiểu lầm và không chính xác. Tr không phải là một chức năng cắt xén, nó là một chức năng thay thế. Hai hoạt động rất khác nhau.
Zane Claes

1
@ZaneClaes Có. OP đã sử dụng thuật ngữ sai để giải thích những gì OP thực sự muốn. Câu trả lời đã chỉ ra cách đạt được kết quả đầu ra.
Arup Rakshit

39

Nếu bạn chỉ muốn xóa hai ký tự đầu tiên và hai ký tự cuối cùng, thì bạn có thể sử dụng các chỉ mục phủ định trên chuỗi:

s = "((String1))"
s = s[2...-2]
p s # => "String1"

Nếu bạn muốn xóa tất cả các dấu ngoặc đơn khỏi chuỗi, bạn có thể sử dụng phương thức xóa trên lớp chuỗi:

s = "((String1))"
s.delete! '()'
p s #  => "String1"

8
Thao tác này sẽ xóa tất cả các dấu ngoặc đơn, ngay cả những dấu ngoặc ở giữa chuỗi, điều này (dường như) không phải là điều OP muốn. Nếu đó là những gì được mong muốn thì đây là giải pháp thanh lịch nhất.
Phục hồi Monica - notmaynard

20

Sử dụng String#gsubvới biểu thức chính quy:

"((String1))".gsub(/^\(+|\)+$/, '')
# => "String1"
"(((((( parentheses )))".gsub(/^\(+|\)+$/, '')
# => " parentheses "

Thao tác này sẽ chỉ xóa các dấu ngoặc đơn xung quanh.

"(((((( This (is) string )))".gsub(/^\(+|\)+$/, '')
# => " This (is) string "

2
+1 cho ví dụ thứ hai (chỉ xóa các dấu ngoặc đơn xung quanh).
Bhavneet Singh Bajwa

20

Đối với những người đi ngang qua này và tìm kiếm hiệu quả, nó trông giống như #delete#trkhoảng giống nhau ở tốc độ và 2-4x nhanh hơn gsub.

text = "Here is a string with / some forwa/rd slashes"
tr = Benchmark.measure { 10000.times { text.tr('/', '') } }
# tr.total => 0.01
delete = Benchmark.measure { 10000.times { text.delete('/') } }
# delete.total => 0.01
gsub = Benchmark.measure { 10000.times { text.gsub('/', '') } }
# gsub.total => 0.02 - 0.04

3
Bốn năm sau ... :-) Tôi thấy nếu tôi tăng điểm chuẩn của bạn lên một vài bậc lớn (1_000_000 lần chạy), với cùng một mã bạn sử dụng ở trên, tôi thực hiện xóa chạy nhanh hơn một chút so với tr, với việc xóa vào khoảng tỷ lệ 0,92 tr, và gsub ít hơn 1,5 lần xóa (thực tế là ~ 1,46 lần xóa và ~ 1,39 tr). tất nhiên là ymmv. Đây là trên Ruby 2.6.3 trên MBP 2018. Cảm ơn bạn đã đo điểm chuẩn cho ba phương pháp này!
likethesky

1

Đây là một cách thậm chí còn ngắn hơn để đạt được điều này:

1) sử dụng Negative character class pattern matching

irb(main)> "((String1))"[/[^()]+/]
=> "String1"

^- Đối sánh bất kỳ thứ gì KHÔNG trong lớp ký tự. Bên trong lớp charachter, chúng tôi có ()

Hoặc với thay thế toàn cầu "AKA: gsub" như những người khác đã đề cập.

irb(main)> "((String1))".gsub(/[)(]/, '')
=> "String1"

Hai câu trả lời của bạn có kết quả khác nhau ((a))b. Lần đầu tiên sẽ chỉ trở lại a, lần thứ hai sẽ trở lạiab
Ulysse BN
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.