Replacing characters in Ruby string according to some rule
In Ruby, I have a string of identical characters -- let's say they're all exclamation points, as in !!!!
. I would like to replace the characters at certain indices with '*' if the integer corresponding to that index meets some criteria.
For example, let's say I want to replace all the characters whose indices are even numbers and are greater than 3. In the string !!!!!!!!
(8 characters long), that开发者_如何学JAVA results in !!!!*!*!
(indices 4 and 6 have been replaced).
What's the most compact way to do this?
Here is a version that will modify an existing string in place:
str = '!!!!!!!!'
str.split('').each_with_index do |ch, index|
str[index] = '*' if index % 2 == 0 and index > 3
end
For those of you who, like me, are obsessed with the endless possibilities that chained enumerators give us:
str = '!!!!!!!!'
res = '!!!!*!*!'
str.replace(str.chars.with_index.inject('') { |s, (c, i)|
next s << c unless i%2 == 0 && i > 3
s << '*'
})
require 'test/unit'
class TestStringReplacement < Test::Unit::TestCase
def test_that_it_replaces_chars_at_even_indices_greater_than_3_with_asterisk
assert_equal res, str
end
end
I'm new to Ruby too, but the enum_with_index function caught my eye.
2nd Update: This is what I'd meant. This code is tested.
"!!!!!!!".split('').enum_with_index.map{|c,i|(i%2==0 and i>3)?'*':c}.inject(""){|z,c|z+c}
i'm new to ruby, but i thought i would give it a go. mikej's answer is much better.
str = '!!!!!!!!'
index = 0
str.each_char { |char|
if (3 < index) && (index % 2 == 0) then
str[index] = '*'
end
index = index + 1
}
puts str
EDIT
Here is a little better solution combining some of the others (has been tested).
str = '!!!!!!!!'
str.split('').each_with_index do |char, index| 3 < index and index % 2 == 0 ? str[index] = '*' : str[index] = char end
puts str
Possibly the most compact you can get (more compact than other solutions for sure), but who knows?
s="!!!!!!!!"
4.step(s.length-1, 2) {|i| s[i]="*"}
puts s
I'd also guess it's probably the most efficient, compared to the other solutions.
how about regexp?
s="!!!!!!!!"
puts s[0..3]+s[4..s.size].gsub(/!{2}/,"*!")
精彩评论