我有一些动态字符串,其字符为X
。 X
可以通过字符串连续显示或分散。我想将X
替换为#
。
例如,abXXcX12XX
。我想要ab#c#12#
。这意味着多个连续的X
必须仅由一个#
替换,如果只有一个X
,则也可以由一个#
替换。
我试过了:
s = "aXX123Xc56XXX"
s.squeeze('X').gsub('X','#') # => "a#123#c56#"
任何优雅的方式或直接的方法来做同样的操作?
答案 0 :(得分:12)
我将使用String#tr_s
进行如下操作:
按照
String#tr
中的说明处理str的副本,然后删除受翻译影响的区域中的重复字符。
s = "aXX123Xc56XXX"
s.tr_s('X','#') # => "a#123#c56#"
答案 1 :(得分:4)
不确定为什么你不会在这里使用gsub? 正则表达式看起来效果很好:
"aXX123Xc56XXX".gsub(/X+/, "#")
=> "a#123#c56#"
这样做的原因是/X+/
会匹配X
字符的一个或多个,因此一行中多个X
只会产生一个匹配并被一个#
替换。
答案 2 :(得分:1)
pry(main)> "aXX123Xc56XXX".gsub(/X+/, "#")
=> "a#123#c56#"
答案 3 :(得分:1)
虽然gsub
和tr_s
都可以完成任务,但这是使用tr_s
的令人信服的理由:
require 'fruity'
STRING = 'aXX123Xc56XXX' * 1000
compare do
using_tr_s { STRING.tr_s('X', '#') }
using_gsub { STRING.gsub(/X+/, '#') }
end
在我的笔记本电脑上运行之后会导致:
Running each test 16 times. Test will take about 1 second.
using_tr_s is faster than using_gsub by 5x ± 0.1
正则表达式引擎已经看到了很多加速,但它仍然会被非锚定查找击败。如果有一种方法可以告诉它从字符串的开头或结尾开始,我们会看到它的速度很快,而且,对于某些搜索/替换操作,我已经看到它超越了其他所有内容。使用的模式至关重要;写得不好的人会使发动机瘫痪,所以要小心你的用途。