我正在测试以下问题的可能解决方案。我提出的前两个解决方案' disembowel' &安培; ' disembowel_2'没有正常运行。我想找出原因。
Disembowel_3是迄今为止我最喜欢的解决方案。但是如果我不明白我的前两个解决方案出了什么问题,我觉得我没有权利使用disembowel_3。
有谁可以帮我弄清楚前两个解决方案有什么问题?
# Write a function disemvowel(string), which takes in a string,
# and returns that string with all the vowels removed. Treat "y" as a
# consonant.
def disemvowel(string)
string_array = string.split
vowels = %w[aeiou]
i = 0
while i < string.length
if vowels.include? string[i] == true
string_array[i] = " "
end
i +=1
end
new_string = string_array.join
new_string = new_string.sub(/\s+/,"")
return new_string
end
def disemvowel_2(string)
string_array = string.split('')
string_array.delete('a','e','i','o','u')
return string_array.join('')
end
# This is my favorite solution.
def disemvowel_3(string)
result = string.gsub(/[aeiou]/i, '')
return result
end
#tests
puts disemvowel("foobar")
puts disemvowel("ruby")
puts disemvowel("aeiou")
答案 0 :(得分:5)
轻微的改变会使dismvowel正常工作。这是固定的,为什么:
1)split
已更改为string.split("")
。没有参数的split
将按空格分割,split("")
将按字符分割。通过此更改,string_array
将成为字符串中每个字符的数组。这也可以使用string.chars
更简洁地完成,这是首选方法。
见:
2)vowels
已更改为字符串。 %w[]
创建了一个单词数组,因此在使用%w[aeiou]
时,vowels
实际上是一个包含1个字符串"aeiou"
的数组。这意味着String#include?
和Array#include?
都不能与每个角色进行比较。将其更改为常量字符串意味着vowels.include?
可以匹配字符。
请参阅:
3)vowels.include?
没有parens ,明确地与true
进行比较。 Ruby工作的方式,表达式string_array[i] == true
的结果传递给vowels.include?
,这不是预期的。
一些可以帮助解决这个问题的风格提示:
== true
)请参阅:
4)sub
更改为gsub
。对sub
的调用只会在字符串中进行一次替换,因此在使用&#34; fb r&#34;进行调用时,只会替换第一个空格,而将字符串&#34; fb r&#34; 。 gsub
执行&#34;全局替换&#34;,在这种情况下,这正是您想要的。
请参阅:
工作disemvowel
函数如下所示:
def disemvowel(string)
string_array = string.split("")
vowels = "aeiou"
i = 0
while i < string.length
if vowels.include?(string[i])
string_array[i] = " "
end
i +=1
end
new_string = string_array.join
new_string = new_string.gsub(/\s+/,"")
return new_string
end
并使用您的测试生成此输出:
fbr
rby
1)支持混合元音元音。
def disemvowel_1_1(string)
string_array = string.split("")
vowels = "aeiouAEIOU"
i = 0
while i < string_array.length
if vowels.include?(string_array[i])
string_array[i] = " "
end
i +=1
end
new_string = string_array.join
new_string = new_string.gsub(/\s+/,"")
return new_string
end
2)始终使用string_array
而不是与string
混合使用。 string
的各种用途在使用string_array
时更合适。这应该被替换。
def disemvowel_1_2(string)
string_array = string.split("")
vowels = "aeiouAEIOU"
i = 0
while i < string_array.length
if vowels.include?(string_array[i])
string_array[i] = " "
end
i +=1
end
new_string = string_array.join
new_string = new_string.gsub(/\s+/,"")
return new_string
end
3)不要将变量用于&#34; aeiou&#34;。这是一个常量表达式,应该写成字符串文字或常量。在这种情况下,将选择一个文字字符串,因为没有用于限制在全局命名空间中使用常量的封闭范围(如果此代码插入到另一个上下文中)。
def disemvowel_1_3(string)
string_array = string.split("")
i = 0
while i < string_array.length
if "aeiouAEIOU".include?(string_array[i])
string_array[i] = " "
end
i +=1
end
new_string = string_array.join
new_string = new_string.gsub(/\s+/,"")
return new_string
end
4)用nil
而不是" "
替换元音字符,以取消gsub
替换。
def disemvowel_1_4(string)
string_array = string.split("")
i = 0
while i < string_array.length
if "aeiouAEIOU".include?(string_array[i])
string_array[i] = nil
end
i +=1
end
new_string = string_array.join
return new_string
end
5)将while
循环转换为Array#each_with_index
以处理数组元素
def disemvowel_1_5(string)
string_array = string.split("")
string_array.each_with_index do |char, i|
if "aeiouAEIOU".include?(char)
string_array[i] = nil
end
end
new_string = string_array.join
return new_string
end
6)将split("")
替换为String#chars
,以获取要处理的字符数组。
def disemvowel_1_6(string)
string_array = string.chars
string_array.each_with_index do |char, i|
if "aeiouAEIOU".include?(char)
string_array[i] = nil
end
end
new_string = string_array.join
return new_string
end
7)通过链接结果减少临时变量的数量。这可以最小化Ruby必须跟踪的单个变量的数量,并减少每次引用变量名时发生的变量查找。
def disemvowel_1_7(string)
string_array = string.chars
string_array.each_with_index do |char, i|
if "aeiouAEIOU".include?(char)
string_array[i] = nil
end
end
new_string = string_array.join
return new_string
end
8)删除显式返回以使用Ruby的基于表达式的返回值。
def disemvowel_1_8(string)
string_array = string.chars
string_array.each_with_index do |char, i|
if "aeiouAEIOU".include?(char)
string_array[i] = nil
end
end.join
end
9)使用Array#map处理字符,而不是Array#each_with_index
。
def disemvowel_1_9(string)
string.chars.map {|char| "aeiouAEIOU".include?(char) ? nil : char }.join
end
1)将delete
替换为delete_if
。 Array#delete
方法只会删除完全匹配,因此在这种情况下,您必须遍历元音才能使其正常工作。但是,Array#delete_if
可让您删除条件,且条件为vowels.include?(element)
。
请参阅:
def disemvowel_2(string)
string_array = string.split('')
string_array.delete_if {|element| "aeiou".include?(element) }
string_array.join('')
end
1)支持混合元音元音。
def disemvowel_2_1(string)
string_array = string.split('')
string_array.delete_if {|element| "aeiouAEIOU".include?(element) }
string_array.join('')
end
2)将split("")
替换为String#chars
,以获取要处理的字符数组。
def disemvowel_2_2(string)
string_array = string.chars
string_array.delete_if {|element| "aeiouAEIOU".include?(element) }
string_array.join('')
end
3)将join('')
更改为join
。 join
方法已经以这种方式加入,因此额外的参数是多余的
def disemvowel_2_3(string)
string_array = string.chars
string_array.delete_if {|element| "aeiouAEIOU".include?(element) }
string_array.join('')
end
4)通过链接结果减少临时变量的数量。这可以最小化Ruby必须跟踪的单个变量的数量,并减少每次引用变量名时发生的变量查找。
def disemvowel_2_4(string)
string.chars.delete_if {|element| "aeiouAEIOU".include?(element) }.join
end
String有一个delete
方法,可以删除所有匹配的字符。鉴于元音,这是一个简单的实现:
def disemvowel_4(string)
string.delete("aeiouAEIOU")
end
请参阅:
我创建了一个像程序一样的单元测试来进行程序化自我测试,而不是仅仅将不受约束的字符串显示到控制台。这将测试函数的每个版本并报告它是否通过测试:
data = [
["foobar", "fbr"],
["ruby", "rby"],
["aeiou", ""],
["AeIoU", ""],
]
data.each do |test|
puts "disemvowel_1 #{disemvowel_1(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_1_1 #{disemvowel_1_1(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_1_2 #{disemvowel_1_2(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_1_3 #{disemvowel_1_3(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_1_4 #{disemvowel_1_4(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_1_5 #{disemvowel_1_5(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_1_6 #{disemvowel_1_6(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_1_7 #{disemvowel_1_7(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_1_8 #{disemvowel_1_8(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_1_9 #{disemvowel_1_9(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_2 #{disemvowel_2(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_2_1 #{disemvowel_2_1(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_2_2 #{disemvowel_2_2(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_2_3 #{disemvowel_2_3(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_2_4 #{disemvowel_2_4(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_3 #{disemvowel_3(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
puts "disemvowel_4 #{disemvowel_4(test[0]) == test[1] ? 'Pass' : 'Fail'}: '#{test[0]}'"
end
这将产生以下输出:
>$ ruby disemvowel.rb
disemvowel_1 Pass: 'foobar'
disemvowel_1_1 Pass: 'foobar'
disemvowel_1_2 Pass: 'foobar'
disemvowel_1_3 Pass: 'foobar'
disemvowel_1_4 Pass: 'foobar'
disemvowel_1_5 Pass: 'foobar'
disemvowel_1_6 Pass: 'foobar'
disemvowel_1_7 Pass: 'foobar'
disemvowel_1_8 Pass: 'foobar'
disemvowel_1_9 Pass: 'foobar'
disemvowel_2 Pass: 'foobar'
disemvowel_2_1 Pass: 'foobar'
disemvowel_2_2 Pass: 'foobar'
disemvowel_2_3 Pass: 'foobar'
disemvowel_2_4 Pass: 'foobar'
disemvowel_3 Pass: 'foobar'
disemvowel_4 Pass: 'foobar'
disemvowel_1 Pass: 'ruby'
disemvowel_1_1 Pass: 'ruby'
disemvowel_1_2 Pass: 'ruby'
disemvowel_1_3 Pass: 'ruby'
disemvowel_1_4 Pass: 'ruby'
disemvowel_1_5 Pass: 'ruby'
disemvowel_1_6 Pass: 'ruby'
disemvowel_1_7 Pass: 'ruby'
disemvowel_1_8 Pass: 'ruby'
disemvowel_1_9 Pass: 'ruby'
disemvowel_2 Pass: 'ruby'
disemvowel_2_1 Pass: 'ruby'
disemvowel_2_2 Pass: 'ruby'
disemvowel_2_3 Pass: 'ruby'
disemvowel_2_4 Pass: 'ruby'
disemvowel_3 Pass: 'ruby'
disemvowel_4 Pass: 'ruby'
disemvowel_1 Pass: 'aeiou'
disemvowel_1_1 Pass: 'aeiou'
disemvowel_1_2 Pass: 'aeiou'
disemvowel_1_3 Pass: 'aeiou'
disemvowel_1_4 Pass: 'aeiou'
disemvowel_1_5 Pass: 'aeiou'
disemvowel_1_6 Pass: 'aeiou'
disemvowel_1_7 Pass: 'aeiou'
disemvowel_1_8 Pass: 'aeiou'
disemvowel_1_9 Pass: 'aeiou'
disemvowel_2 Pass: 'aeiou'
disemvowel_2_1 Pass: 'aeiou'
disemvowel_2_2 Pass: 'aeiou'
disemvowel_2_3 Pass: 'aeiou'
disemvowel_2_4 Pass: 'aeiou'
disemvowel_3 Pass: 'aeiou'
disemvowel_4 Pass: 'aeiou'
disemvowel_1 Fail: 'AeIoU'
disemvowel_1_1 Pass: 'AeIoU'
disemvowel_1_2 Pass: 'AeIoU'
disemvowel_1_3 Pass: 'AeIoU'
disemvowel_1_4 Pass: 'AeIoU'
disemvowel_1_5 Pass: 'AeIoU'
disemvowel_1_6 Pass: 'AeIoU'
disemvowel_1_7 Pass: 'AeIoU'
disemvowel_1_8 Pass: 'AeIoU'
disemvowel_1_9 Pass: 'AeIoU'
disemvowel_2 Pass: 'AeIoU'
disemvowel_2_1 Pass: 'AeIoU'
disemvowel_2_2 Pass: 'AeIoU'
disemvowel_2_3 Pass: 'AeIoU'
disemvowel_2_4 Pass: 'AeIoU'
disemvowel_3 Pass: 'AeIoU'
disemvowel_4 Pass: 'AeIoU'
我编写了一个基准程序来测试每个实现的性能。这是基准程序:
Times = 5_000
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*(),./<>?;':\"[]{}\\|-=_+`~".chars
array = Times.times.map { |n| "#{chars.sample(n)}" }
puts "============================================================="
puts RUBY_DESCRIPTION
Benchmark.bm(15) do |x|
dismevowel_1_report = x.report("disemvowel_1:") { array.each {|s| disemvowel_1(s) } }
dismevowel_1_1_report = x.report("disemvowel_1_1:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_1_2_report = x.report("disemvowel_1_2:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_1_3_report = x.report("disemvowel_1_3:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_1_4_report = x.report("disemvowel_1_4:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_1_5_report = x.report("disemvowel_1_5:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_1_6_report = x.report("disemvowel_1_6:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_1_7_report = x.report("disemvowel_1_7:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_1_8_report = x.report("disemvowel_1_8:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_1_9_report = x.report("disemvowel_1_9:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_2_report = x.report("disemvowel_2:") { array.each {|s| disemvowel_2(s) } }
dismevowel_2_1_report = x.report("disemvowel_2_1:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_2_2_report = x.report("disemvowel_2_2:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_2_3_report = x.report("disemvowel_2_3:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_2_4_report = x.report("disemvowel_2_4:") { array.each {|s| disemvowel_1_1(s) } }
dismevowel_3_report = x.report("disemvowel_3:") { array.each {|s| disemvowel_3(s) } }
dismevowel_4_report = x.report("disemvowel_4:") { array.each {|s| disemvowel_4(s) } }
end
这是基准的输出:
=============================================================
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14]
user system total real
disemvowel_1: 2.630000 0.010000 2.640000 ( 3.487851)
disemvowel_1_1: 2.300000 0.010000 2.310000 ( 2.536056)
disemvowel_1_2: 2.360000 0.010000 2.370000 ( 2.651750)
disemvowel_1_3: 2.290000 0.010000 2.300000 ( 2.449730)
disemvowel_1_4: 2.320000 0.020000 2.340000 ( 2.599105)
disemvowel_1_5: 2.360000 0.010000 2.370000 ( 2.473005)
disemvowel_1_6: 2.340000 0.010000 2.350000 ( 2.813744)
disemvowel_1_7: 2.380000 0.030000 2.410000 ( 3.663057)
disemvowel_1_8: 2.330000 0.010000 2.340000 ( 2.525702)
disemvowel_1_9: 2.290000 0.010000 2.300000 ( 2.494189)
disemvowel_2: 2.490000 0.000000 2.490000 ( 2.591459)
disemvowel_2_1: 2.310000 0.010000 2.320000 ( 2.503748)
disemvowel_2_2: 2.340000 0.010000 2.350000 ( 2.608350)
disemvowel_2_3: 2.320000 0.010000 2.330000 ( 2.820086)
disemvowel_2_4: 2.330000 0.010000 2.340000 ( 2.735653)
disemvowel_3: 0.070000 0.000000 0.070000 ( 0.070498)
disemvowel_4: 0.020000 0.000000 0.020000 ( 0.018580)
String#delete
方法大致优于除String#gsub
以外的所有手动解决方案超过100倍,并且比String#gsub
快2.5倍。它非常易于使用,并且优于其他一切;这很容易成为最佳解决方案。
答案 1 :(得分:3)
这第一个解决方案是官僚主义的,在代码和风格方面存在一些错误。
"asdfg".split
,结果将是["asdfg"]
,而不是['a','s','d','f','g']
,正如您所期望的那样。你的第二个解决方案,虽然比第一个解决方案简单得多,但问题是 engineermnky 。 Array#delete不带五个参数。
最后,你的第三个解决方案虽然运行良好,但可以用更简单的方式编写:
def disemvowel_3(string)
string.gsub(/[aeiou]/i, '')
end
我一直在告诉人们,在Ruby方法的最后,你不需要明确返回。默认情况下,它将返回计算的最后一个值,无论它是什么。
如果您允许我建议,另一种可能的解决方案是以下列方式使用 Array#reject :
def disemvowel(str)
vowels = %w[a e i o u]
str.each_char.to_a.reject{ |item| vowels.include?(item) }.join
end
答案 2 :(得分:0)
这是一种干净易懂的方法。
首先,您的元音已定义为变量。
string#chars使您的字符串变成字符数组。
#select遍历字符串数组,查看每个项目。如果不包括该项目(!),则将其转换为小写形式的元音。 #select将该项目插入符合所需项目标准的项目数组中。
没有任何参数的#join会重新组合所有字符,但不包括元音。
这将适用于大写和小写字母。还有标点和空格。
您将获得减去元音的输入。
def disemvowl(string)
vowels = 'aeiou'
string.chars.select { |char| !vowels.include?(char.downcase) }.join
end
#p disemvowl('string') # => "strng"
#p disemvowl('s trin g!?') # => "s trn g!?"
答案 3 :(得分:0)
以下是编写消除元音的方法的几种不同方法。它们分为破坏性和非破坏性两类。这些方法的注释提供了有关这些方法的更多详细信息。在大多数情况下,每个类别中的方法之间的区别在于格式。还有其他需要进一步详细说明的注释。我希望这会有所帮助。
# These methods are what is referred to as destructive.
# delete!() will delete from the original item
def disemvowl(string)
vowels = 'aeiou'
string.each_char { |char| vowels.include?(char.downcase) ? string.delete!(char) : nil }
end
def disemvowl(string)
vowels = 'aeiou'
string.each_char { |char| string.delete!(char) if vowels.include?(char.downcase) }
end
def disemvowl(string)
vowels = 'aeiou'
string.each_char { |char|
string.delete!(char) if vowels.include?(char.downcase)
}
end
def disemvowl(string)
vowels = 'aeiou'
string.each_char do |char|
string.delete!(char) if vowels.include?(char.downcase)
end
end
# These are nondestructive
# The original is not modified and you are returning a string of selected items.
# Do not forget to flip your operation with (!)
def disemvowl(string)
vowels = 'aeiou'
string_new = ''
string.each_char { |char| !vowels.include?(char.downcase) ? string_new += char : nil }
string_new
end
def disemvowl(string)
vowels = 'aeiou'
string_new = ''
string.each_char { |char| string_new += char if !vowels.include?(char.downcase) }
string_new
end
def disemvowl(string)
vowels = 'aeiou'
string_new = ''
string.each_char { |char|
string_new += char if !vowels.include?(char.downcase)
}
string_new
end
def disemvowl(string)
vowels = 'aeiou'
string.each_char do |char|
string.delete!(char) if !vowels.include?(char.downcase)
end
end
# This is what I would do if nondestructive is desired.
# This was my original submission. It is explained step by step there.
# There are many ways to perform a task.
# Because sometimes it matters how you achieve your outcome.
# I created this more elaborate response.
def disemvowl(string)
vowels = 'aeiou'
string.chars.select { |char| !vowels.include?(char.downcase) }.join
end
# This is what I would do if changing the original is desired.
# This is an if else statement with Ternary Operators ? :
# I use logic as much as possible because it will out perform calling a function to do the same thing
# |thing| this is true about(thing) ? this will happen : <= or this }
# In this case I am saying |char| true(char) ? delete char from string : do nothing }
def disemvowl(string)
vowels = 'aeiou'
string.each_char { |char| vowels.include?(char.downcase) ? string.delete!(char) : nil }
end
#p disemvowl('string') # => "strng"
#p disemvowl('As trIin g!?') # => "s trn g!?"