这是一个将元音改为索引的程序:
my $category_set=NotificationIRPConstDefs::NotificationCategorySetOpt->new();
$category_set->value(["1f1"]);
有谁能告诉我为什么它没能通过'Codewars是世界上最好的网站'?
当我尝试传递类似的测试用例时:
def vowel_2_index(string)
return '' if string.nil?
arr = string.enum_for(:scan,/[aeiou]/i).map {Regexp.last_match.begin(0) }
s_arr = arr.map{|x| x+1 }
arr.each_with_index{|x,y| string[x] = s_arr[y].to_s}
string
end
输出如下内容:
Test.assert_equals(vowel_2_index('Codewars is the best site in the world'),'C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld')
答案 0 :(得分:3)
正如您所看到的,当您开始用位置替换元音时,它的位置是单个数字(即1
或5
),但是当位置变为2位数时({{ 1}}和更大)所有找到的索引开始转移,10
信息不再正确。
我建议使用gsub
,因为你想进行全局搜索和替换,你几乎做得对:
arr
答案 1 :(得分:3)
以下所有内容均指:
str = 'Codewars is the best site in the world'
至于你遇到的问题,让我们分解一下:
enum = str.enum_for(:scan,/[aeiou]/i)
#=> #<Enumerator: "Codewars is the best site in the world":scan(/[aeiou]/i)>
要查看由map
传递给其块的此枚举器的元素,我们可以将其转换为数组:
enum.to_a
#=> ["o", "e", "a", "i", "e", "e", "i", "e", "i", "e", "o"]
继续:
arr = enum.map {Regexp.last_match.begin(0) }
#=> [1, 3, 5, 9, 14, 17, 22, 24, 26, 31, 34]
s_arr = arr.map{|x| x+1 }
#=> [2, 4, 6, 10, 15, 18, 23, 25, 27, 32, 35]
arr.each_with_index{|x,y| string[x] = s_arr[y].to_s}
#=> [1, 3, 5, 9, 14, 17, 22, 24, 26, 31, 34]
str
#=> "C2d4w6rs 10s t15e18bes232527ite32i35 the world"
该方法应返回:
#=> "C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld"
所以你看到分歧开始于'h'
中的'the'
,它位于索引13
。将10
的元素arr
传递给块时会发生此问题。此时,
str
#=> "C2d4w6rs is the best site in the world"
块变量设置为:
x,y = [10, 3]
x #=> 10
y #=> 3
所以块计算是:
str[10] = s_arr[3].to_s
#=> = "10"
现在:
str
#=> "C2d4w6rs 10s the best site in the world"
如您所见,10
之后的所有字母的索引都增加了一个。这不是一个问题,因为前三个字符每个都用一位数字代替。 arr
和s_arr
的其余元素现在由一个元素关闭,在下一个替换之后,剩余的元素的索引将关闭两个,依此类推。
*********
我会使用以下方法之一。
VOWELS = 'aeiouAEIOU'
<强>#1 强>
pos = '0'
str.gsub(/./) { |c| pos.next!; VOWELS.include?(c) ? pos : c }
#=> "C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld"
<强>#2 强>
str.each_char.with_index(1).map { |c,i| VOWELS.include?(c) ? i.to_s : c }.join
#=> "C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld"
#3
str.size.times.map { |i| VOWELS.include?(str[i]) ? (i+1).to_s : str[i] }.join
#=> "C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld"
我稍微偏爱#1,因为它直接对字符串进行操作,而不是创建数组然后将其元素连接回字符串。而且,我认为它读得最好。
答案 2 :(得分:1)
str = 'Codewars is the best site in the world'
您可以将字符串拆分为字符数组,并使用with_index(1)将每个值与regex.Am进行比较,因为数组基于零。
str.split(//).map.with_index(1){|k,v| /[aeiou]/=~k ? v : k}.join
结果是:
#=> 'C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld'