如何在Ruby中从字符串中删除特定字符?

104

我有几个看起来像这样的字符串:

"((String1))"

它们的长度都不同。我如何在循环中删除所有这些字符串中的括号?


2
移除括号,或从一个“随机”的字符串中删除前两个和后两个字符?(真的是随机的吗?) - Reinstate Monica -- notmaynard
"((String1))"[2...-2] # => "String1""((String1))"[2...-2] # => "String1" - Reinstate Monica -- notmaynard
1
http://www.ruby-doc.org/core-1.9.3/String.html - Reinstate Monica -- notmaynard
你正在请求一个循环来改变许多字符串,这些字符串是如何存储的? - hirolau
我知道如何循环遍历所有字符串,我只是想要字符串操作部分,抱歉我的措辞有些奇怪。 - Cristiano
以下是一位厨师可能会喜欢的解决方案:def chop_chop(s) chop_one_way(chop_one_way(s,')').reverse,'(').reverse enddef chop_one_way(s,c); s.chop! while s[-1] == c; s; end chop_chop "(((abc)))" # => "abc" - Cary Swoveland
6个回答

197

使用String#tr方法按照下面的方式执行:

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

9
还有一个破坏性版本的 tr! 函数可以原地修改字符串,例如 my_string.tr!(')(','') - bonh
11
请注意,此函数不是从开头或结尾截取文本,而是对字符串内的所有文本进行完全替换。 - Jordan
3
误导和不正确。Tr 不是一个修剪函数,它是一个替换函数。这两个操作非常不同。 - Zane Claes
1
@ZaneClaes 是的。OP使用了错误的术语来解释实际上OP想要什么。答案已经展示了如何实现输出。 - Arup Rakshit
属性错误:'str'对象没有'tr'属性。 - Nathan B
@NathanB Ruby 的版本是多少? - Arup Rakshit

49
如果你只想删除字符串的前两个字符和最后两个字符,那么可以使用字符串的负索引
s = "((String1))"
s = s[2...-2]
p s # => "String1"

如果你想从字符串中删除所有括号,可以在字符串类上使用delete方法:

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

11
这将删除所有括号,即使是字符串中间的括号,这似乎不是原帖作者想要的。如果这正是所需的,那么这是最优雅的解决方案。 - Reinstate Monica -- notmaynard

30

对于那些查找性能的人,看起来#delete#tr速度大约相同,并且比gsub快2-4倍。

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

4
四年后... :-) 我发现,如果我将你的基准测试提高几个数量级(1_000_000次运行),那么用上面相同的代码,我确实发现 delete 的运行速度比 tr 稍微快一些,delete 大约是 tr 的 0.92 倍,并且 gsub 比 delete 快不到 1.5 倍(实际上是 delete 的大约 1.46 倍和 tr 的大约 1.39 倍)。当然,结果可能因人而异。这是在 2018 年 MBP 13 上的 Ruby 2.6.3 上进行的基准测试。感谢您对这三种方法进行基准测试! - likethesky

23

使用正则表达式与String#gsub方法:

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

这将仅移除周围的括号。

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

2
第一个例子加1,第二个例子去掉括号即可。 - Bhavneet Singh Bajwa

1
这里有一种更简单的方法来实现这个目标:
1)使用“负字符类模式匹配”。
irb(main)> "((String1))"[/[^()]+/]
=> "String1"

^ - 匹配不在字符类中的任何内容。在字符类内部,我们有 ()

或者使用全局替换 "AKA: gsub",就像其他人已经提到的那样。

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

你的两个答案在 ((a))b 上有不同的结果。第一个只会返回 a,而第二个将返回 ab - Ulysse BN

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接