In How do I limit the number of replacements when using gsub?, someone suggested the following way to do a limited number of substitutions:
str = 'aaaaaaaaaa'
count = 5
p str.gsub(/a/){if count.zero? then $& else count -= 1; 'x' end}
# => "xxxxxaaaaa"
It works, but the code mixes up how many times to substitute (5) with what the substitution should be ("x" if there should be a substitution, $&
otherwise). Is it possible to seperate the two out?
(If it's too hard to seperate the two things out in this scenario, but it can be done in some other scenarios, post that as an answer)
How about just extracting the replacement as an argument and encapsulating the counter by having the block close over it inside a method?
str = "aaaaaaaaaaaaaaa"
def replacements(replacement, limit)
count = limit
lambda { |original| if count.zero? then original else count -= 1; replacement end }
end
p str.gsub(/a/, &replacements("x", 5))
You can make it even more general by using a block for the replacement:
def limit(n, &block)
count = n
lambda do |original|
if count.zero? then original else count -= 1; block.call(original) end
end
end
Now you can do stuff like
p str.gsub(/a/, &limit(5) { "x" })
p str.gsub(/a/, &limit(5, &:upcase))