我正在尝试编写一个ruby函数,它接受一串单词并将其转换为 Pig Latin 。我将字符串分解为数组,并尝试迭代每个元素。当"吃馅饼"投入,结果是"吃即#34;但我不确定为什么。
string = "eat pie"
array = string.split(" ")
array.map do |word|
if word[0].chr == "a" || word[0].chr == "e" || word[0].chr == "i" || word[0].chr == "o" || word[0].chr == "u"
word = word + "ay"
elsif word[1].chr == "a" || word[1].chr == "i" || word[1].chr == "o" || word[1].chr == "u"
temp = word[0]
word[0] = ""
word = word + temp
word = word + "ay"
elsif word[2].chr == "a" || word[2].chr == "i" || word[2].chr == "o" || word[2].chr == "u"
temp = word[0] + word[1]
word[0] = ""
word[0] = ""
word = word + temp
word = word + "ay"
else ## three consonants
temp = word[0] + word[1] + word[2]
word[0] = ""
word[0] = ""
word[0] = ""
word = word + temp
word = word + "ay"
end ## end of if statement
end ## end of iteration
puts array.join(" ")
答案 0 :(得分:2)
您看到的输出有两个不同的原因:
1)在Ruby中,Array.map
返回 new 数组。它不会修改迭代的数组。这导致您对阵列的一些修改丢失。
来自Ruby docs:
为self的每个元素调用给定的块一次。 创建一个包含块返回值的新数组。
您应该将结果分配给新变量,或者使用Array.map!
代替,将修改数组的内容。
array = string.split(" ")
mapped = array.map do |word|
# ...
end
mapped.join(" ")
2)虽然由于使用map
而导致某些修改丢失,但您正在修改数组中的某些字符串,这就是您看到eat ie
而不是{{1}的原因(缺少eat pie
)。
要说明此问题,请查看以下代码:
p
在Ruby中,当您访问字符串中的第一个字符(使用word = "pie"
word[0] = ""
puts word #=> "ie"
)并为其分配值时,Ruby 会改变该字符串,并且不会返回新的字符串副本。
您应该创建一个新字符串,而不是直接更改字符:
[0]
答案 1 :(得分:2)
同意所提供的其他答案,这是一个稍微简洁的代码版本,以防它帮助您。
input = 'pig latin is awesome'
arr = input.split(' ').map do |wrd|
if %w(a e i o u).include? wrd[0]
wrd + 'ay'
elsif %w(a i o u).include? wrd[1]
wrd[1..-1] + wrd[0] + 'ay'
elsif %w(a i o u).include? wrd[2]
wrd[2..-1] + wrd[0] + wrd[1] + 'ay'
else
wrd[3..-1] + wrd[0] + wrd[1] + wrd[2] + 'ay'
end
end.join(' ')
puts arr
答案 2 :(得分:1)
array.map
并非旨在改变数组,因此您要做的是newarray = array.map { ... }
或array.map! do ... end
。
在循环内部,每个word
都是一个字符串对象,通过调用word[0] = ""
进行变异。通过调用word = word + "ay"
,您将丢弃原始字符串的引用,但不会覆盖它。虽然word = word + "ay"
是块中执行的最后一个语句,但它会被计为块的返回值。
我打赌你仍然感到困惑,因为整体并不那么简单所以你可能想要阅读一些关于 mutable 和 immutable 对象和功能和命令式编程。