在Ruby中删除字符串中的元音

在Ruby中删除字符串中的元音,ruby,string,replace,Ruby,String,Replace,我正在测试以下问题的可能解决方案。我提出的前两个解决方案“disembowel”和“disembowel_2”运行不正常。我想知道原因 到目前为止,我最喜欢的解决方案是取出内脏。但我觉得如果我不明白我的前两个解决方案哪里出了问题,我就没有权利使用disembowel_3 有人能帮我找出前两个解决方案的问题吗 # Write a function disemvowel(string), which takes in a string, # and returns that string with

我正在测试以下问题的可能解决方案。我提出的前两个解决方案“disembowel”和“disembowel_2”运行不正常。我想知道原因

到目前为止,我最喜欢的解决方案是取出内脏。但我觉得如果我不明白我的前两个解决方案哪里出了问题,我就没有权利使用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") 
#编写一个函数disemvowel(string),它接受一个字符串,
#并返回删除所有元音的字符串。将“y”视为
#辅音。
def disemvowel(字符串)
string\u数组=string.split
元音=%w[aeiou]
i=0
而我
第一种解决方案是官僚主义的,在代码和风格上存在一些错误

  • 您将字符串拆分为一个单独的字符数组,但使用string\u array=string.split时出错。或string\u array=string.split(“”)string\u array=string.chars(最佳选项)或string\u array=string.each\u char.to\u a。如果您执行
    “asdfg”.split
    ,结果将是
    [“asdfg”]
    ,而不是
    ['a'、's'、'd'、'f'、'g']
    ,正如您所期望的那样
  • 然后不使用这个(假定的)数组,而是继续使用原始字符串。如果您打算这样做,为什么要尝试拆分原始字符串
  • 最后,返回到使用数组,根据原始字符串中发生的情况对其进行更改。正如您可能看到的那样,您一直在使用太多的对象,而这些对象肯定超出了您的需要。这违反了KISS原则,因此导致运行不正常
您的第二个解决方案虽然比第一个简单得多,但却指出了问题所在。数组#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

微小的更改将使disemvowel正常工作。这就是被修复的原因:

迪斯韦尔 虫子 1)
split
已更改为
string.split(“”
)<没有参数的代码>拆分将按空格拆分,
拆分(“”
将按字符拆分。通过此更改,
string\u数组
将成为字符串中每个字符的and数组。这也可以通过
string.chars
更简洁地完成,这是首选方法

见:

2)
元音
已更改为字符串
%w[]
创建一个单词数组,所以当使用
%w[aeiou]
时,
元音实际上是一个由1个字符串组成的数组
“aeiou”
。这意味着无论是
String#include?
还是
Array#include?
都无法对每个字符进行比较。将其更改为常量字符串意味着
元音.include?
可以与字符匹配

见:

3)
元音。include?
没有paren,并且与
true
进行了显式比较。按照Ruby的工作方式,表达式
string\u array[i]==true
的结果被传递给
元音。include?
,这不是预期的结果

以下是一些有助于实现这一点的风格提示:

  • 与true的比较应该是隐式的(例如,不要使用
    ==true
  • 调用函数或方法时使用参数
见:

  • 部分
4)
sub
更改为
gsub
。对
sub
的调用只会替换字符串中的一个空格,因此当使用“fbr”调用时,只替换第一个空格,留下字符串“fbr”
gsub
执行“全局替换”,这正是您在本例中想要的

见:

第一个工作版本 工作
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
清理 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
def disemvowel_2_1(string)
  string_array = string.split('')
  string_array.delete_if {|element| "aeiouAEIOU".include?(element) }
  string_array.join('')
end
3) 不要将变量用于“aeiou”。这是一个常量表达式,应该写为字符串文字或常量。在本例中,将选择一个文本字符串,因为没有封闭范围来约束全局名称空间中常量的使用(如果此代码被插入到另一个上下文中)

5) 将
while
循环转换为
数组#每个带有_索引的_
,以处理数组元素

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) 使用
String#chars
替换
split(“”
),以获取要处理的字符数组

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
def disemvowel_2_2(string)
  string_array = string.chars
  string_array.delete_if {|element| "aeiouAEIOU".include?(element) }
  string_array.join('')
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
def disemvowel_2_4(string)
  string.chars.delete_if {|element| "aeiouAEIOU".include?(element) }.join
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) 使用数组#映射来处理字符,而不是使用
数组#每个带有_索引的

def disemvowel_1_9(string)
  string.chars.map {|char| "aeiouAEIOU".include?(char) ? nil : char }.join
end
迪斯韦尔2 虫子 1) 替换
删除<
def disemvowel_1_9(string)
  string.chars.map {|char| "aeiouAEIOU".include?(char) ? nil : char }.join
end
def disemvowel_2(string)
  string_array = string.split('')
  string_array.delete_if {|element| "aeiou".include?(element) }
  string_array.join('')
end 
def disemvowel_2_1(string)
  string_array = string.split('')
  string_array.delete_if {|element| "aeiouAEIOU".include?(element) }
  string_array.join('')
end
def disemvowel_2_2(string)
  string_array = string.chars
  string_array.delete_if {|element| "aeiouAEIOU".include?(element) }
  string_array.join('')
end
def disemvowel_2_3(string)
  string_array = string.chars
  string_array.delete_if {|element| "aeiouAEIOU".include?(element) }
  string_array.join
end
def disemvowel_2_4(string)
  string.chars.delete_if {|element| "aeiouAEIOU".include?(element) }.join
end
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)
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!?"
# 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!?"