替换直到删除所有匹配项

Replace until all occurrences are removed

我有以下字符串:

",||||||||||||||"
",|||||a|||||,|"

我想实现 所有出现的 ",|" 都替换为 ",,"

输出应如下所示:

",,,,,,,,,,,,,,,"
",,,,,,a|||||,,"

当我在字符串上 运行 .gsub(',|', ',,') 时,我没有得到想要的输出。

",,|||||||||||||"
",,||||a|||||,,"

那是因为它没有运行 gsub几次。 有没有类似的方法运行递归

正则表达式匹配不能重叠。因为火柴是用来替换的,所以你不能那样做。这里有两个解决方法:

str = ",|||||a|||||,|"
while str.gsub!(/,\|/, ',,'); end

str = ",|||||a|||||,|"
str.gsub!(/,(\|+)/) { "," * (.length + 1) }
smoke_weed_every_day = lambda do |piper|
  commatosed = piper.gsub(',|', ',,')
  commatosed == piper ? piper : smoke_weed_every_day.(commatosed)
end

smoke_weed_every_day.(",||||||||||||||") # => ",,,,,,,,,,,,,,,"
smoke_weed_every_day.(",|||||a|||||,|")  # => ",,,,,,a|||||,,"

来自我的旧图书馆。此方法迭代直到块输出等于其输入:

def loop_until_convergence(x)
  x = yield(previous = x) until previous == x
  x
end

puts loop_until_convergence(',||||||||||||||') { |s| s.gsub(',|', ',,') }
# ",,,,,,,,,,,,,,,"
puts loop_until_convergence(',|||||a|||||,|') { |s| s.gsub(',|', ',,') }
# ",,,,,,a|||||,,"

作为奖励,您可以计算 very few iterations 的平方根:

def root(n)
  loop_until_convergence(1) { |x| 0.5 * (x + n / x) }
end

p root(2)
# 1.414213562373095
p root(3)
# 1.7320508075688772

与@Amandan 的第二个解决方案一样,在没有进一步更改之前无需迭代。

COMMA = ','
PIPE  = '|'

def replace_pipes_after_comma(str)
  run = false
  str.gsub(/./) do |s|
    case s
    when PIPE
      run ? COMMA : PIPE    
    when COMMA
      run = true
      COMMA
    else
      run = false
      s
    end
  end
end

replace_pipes_after_comma ",||||||||||||||"
  #=>                     ",,,,,,,,,,,,,,," 
replace_pipes_after_comma ",|||||a|||||,|"
  #=>                     ",,,,,,a|||||,,"