我目前在我的工作中有这个方法用于Ruby任务,我需要将用户输入的名称中的元音和辅音更改为下一个连续的元音/辅音,所以(a = e,e = i等等)和辅音的相同过程(b = c,d = f等)。我用“简单”的方式做到了,但现在我需要改变它,相反,我正在迭代一个数组并改变元音/辅音。
我是迭代的新手,所以我遇到了麻烦。
这是我原来的方法:
puts "What is your full name?"
full_name = gets.chomp
def vowelreplace(full_name)
vowels = 'aeiou'
replacements = 'eioua'
full_name.tr(vowels, replacements)
end
name_next_vowel = vowelreplace(full_name)
p name_next_vowel
def consonantreplace(name_next_vowel)
consonants = 'bcdfghjklmnpqrstvwxyz'
replacements = 'cdfghjklmnpqrstvwxyzb'
name_next_vowel.tr(consonants, replacements)
end
new_spyname = consonantreplace(name_next_vowel)
p new_spyname
以下是我开始使用数组和块方法在下面进行更改的内容。这样做是否有更简单的冗长方式?是否有一种.next方式这样做,或者一般来说,更有效的方式?
puts "What is your first name?"
first_name = gets.chomp
arr = first_name.split("")
p arr
arr.map! { |element|
if(element == "a")
"e"
elsif(element == "e")
"i"
elsif(element == "i")
"o"
elsif(element == "o")
"u"
elsif(element == "u")
"a"
else
element
end
}
p arr
new_arr = arr
new_arr.map! { |element|
if(element == "b")
"c"
elsif(element == "c")
"d"
elsif(element == "d")
"f"
elsif(element == "f")
"g"
elsif(element == "g")
"h"
elsif(element == "h")
"j"
elsif(element == "j")
"k"
elsif(element == "k")
"l"
elsif(element == "l")
"m"
elsif(element == "m")
"n"
elsif(element == "n")
"p"
elsif(element == "p")
"q"
elsif(element == "q")
"r"
elsif(element == "r")
"s"
elsif(element == "s")
"t"
elsif(element == "t")
"v"
elsif(element == "v")
"w"
elsif(element == "w")
"x"
elsif(element == "x")
"y"
elsif(element == "y")
"z"
elsif(element == "z")
"b"
else
element
end
}
p new_arr
arr.join("")
答案 0 :(得分:1)
你可以在地图循环中使用一系列case语句吗?
arr.map! { |element|
case element
when "a" then "e"
when "e" then "i"
when "i" then "o"
when "o" then "u"
when "u" then "a"
end
}
辅音也一样。
答案 1 :(得分:1)
我喜欢tr
方法,但是如果你想要类似于next
的东西,那么Array#rotate
可能是一个不错的选择;这是一个例子:
def letter_swap(full_name)
vowels = %w(a e i o u)
consonants = %w(b c d f g h j k l m n p q r s t v w x y z)
full_name.each_char.with_object("") do |char, new_name|
if vowels.include?(char)
new_name << vowels.rotate(vowels.index(char) + 1).first
elsif consonants.include?(char)
new_name << consonants.rotate(consonants.index(char) + 1).first
else
new_name << char
end
end
end
当然你可以干这个代码,但代价是可读性(IMO);例如:
def letter_swap(full_name)
letters = [%w(a e i o u), %w(b c d f g h j k l m n p q r s t v w x y z)]
full_name.each_char.with_object("") do |char, new_name|
group = letters.find { |group| group.include?(char) }
new_name << (group.nil? ? char : group.rotate(group.index(char) + 1).first)
end
end
答案 2 :(得分:1)
您可以将String#tr与字符数组一样使用,但tr
的时间复杂度为O(n),因为第一个参数的字符在尝试时会按顺序检查找到匹配。如果要进行大量此类查找,则使用具有几乎恒定的查找时间的散列会快得多。您可以编写如下方法。
<强>代码强>
VOWELS = %w|a e i o u|
#=> ["a", "e", "i", "o", "u"]
NEXT_VOWEL = VOWELS.zip(VOWELS.rotate(1)).to_h
#=> {"a"=>"e", "e"=>"i", "i"=>"o", "o"=>"u", "u"=>"a"}
CONSONANTS = ('a'..'z').to_a - VOWELS
#=> ["b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n",
# "p", "q", "r", "s", "t", "v", "w", "x", "y", "z"]
NEXT_CONSONANT = CONSONANTS.zip(CONSONANTS.rotate(1)).to_h
#=> {"b"=>"c", "c"=>"d", "d"=>"f", "f"=>"g", "g"=>"h", "h"=>"j", "j"=>"k",
# "k"=>"l", "l"=>"m", "m"=>"n", "n"=>"p", "p"=>"q", "q"=>"r", "r"=>"s",
# "s"=>"t", "t"=>"v", "v"=>"w", "w"=>"x", "x"=>"y", "y"=>"z", "z"=>"b"}
def code(arr)
arr.map { |c| NEXT_CONSONANT[c] || NEXT_VOWEL[c] || c }
end
据推测,你也需要能够解码。您可以使用方法Hash#invert编写解码方法,如下所示。
PREVIOUS_VOWEL = NEXT_VOWEL.invert
# => {"e"=>"a", "i"=>"e", "o"=>"i", "u"=>"o", "a"=>"u"}
PREVIOUS_CONSONANT = NEXT_CONSONANT.invert
#=> {"c"=>"b", "d"=>"c", "f"=>"d", "g"=>"f", "h"=>"g", "j"=>"h", "k"=>"j", "l"=>"k",
# "m"=>"l", "n"=>"m", "p"=>"n", "q"=>"p", "r"=>"q", "s"=>"r", "t"=>"s", "v"=>"t",
# "w"=>"v", "x"=>"w", "y"=>"x", "z"=>"y", "b"=>"z"}
def decode(arr)
arr.map { |c| PREVIOUS_CONSONANT[c] || PREVIOUS_VOWEL[c] || c }
end
示例强>
首先编码数组。
arr = "billy-bob".chars
#=> ["b", "i", "l", "l", "y", "-", "b", "o", "b"]
a = code(arr)
#=> ["c", "o", "m", "m", "z", "-", "c", "u", "c"]
a.join
#=> "commz-cuc"
然后解码它。
a = decode ["c", "o", "m", "m", "z", "-", "c", "u", "c"]
#=> ["b", "i", "l", "l", "y", "-", "b", "o", "b"]
a.join
#=> "billy-bob"
<强>解释强>
考虑表达式
NEXT_CONSONANT[c] || NEXT_VOWEL[c] || c
方法code
中的。假设c = 'd'
。然后是NEXT_COSONANT['d'] #=> 'f'
,所以我们有
'f' || NEXT_VOWEL[c] || c
由于'f'
是真实的,因此会返回'f'
。 Ruby没有理由评估NEXT_VOWEL[c] || c
所以她没有。
现在假设c = 'e'
。然后,由于NEXT_CONSONANT
没有键'e'
,NEXT_CONSONANT['e'] #=> nil
,表达式变为
nil || NEXT_VOWEL[c] || c
因此有必要评估NEXT_VOWEL['e']
。如果返回'i'
,这是真实的,则会返回'i'
,并且无需评估c
。
最后,如果c = '-'
,我们会获得
nil || nil || c
因此评估并返回c
。