开发者

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}/,"*!")
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜