我想在第一个元音之前提取一个字符串中的所有辅音,最好不要使用regex。例如,如果我有单词truck,我想提取“tr”,对于“street”,我想提取“str”。
我尝试了以下操作,但收到错误wrong number of arguments (given 0, expected 1) for the execution of the block in vowels.
有人能解释错误在哪里或建议一个更简单的方法来做这个吗?

vowels = ["a", "e", "i", "o", "u"]

def vowels(words)
  letters = words.split("")
  consonants = []
  letters.each do |letter|
    consonants << letter until vowels.include?(letter)
  end
  consonants
end

最佳答案

注意,函数和数组的名称相同,vowels。这会引起混淆——您可能认为您正在对全局includes?数组调用vowels,但实际上,您的代码试图在没有参数的情况下递归调用同名函数,因此出现错误。由于ruby允许不带括号的函数调用,ruby处理这一行:

vowels.include?(letter)

作为
vowels().include?(letter) # <- wrong number of arguments!

将函数名更改为“元音”以外的其他名称会导致此错误,这更有意义:
undefined local variable or method `vowels' for main:Object
(repl):7:in `block in function_formerly_known_as_vowels'
(repl):6:in `each'
(repl):6:in `function_formerly_known_as_vowels'
(repl):12:in `<main>'

这导致了根本原因:破坏封装。vowels函数试图访问全局范围内的状态。这是一个糟糕的实践(在这段代码中不起作用,因为vowels数组实际上不是全局的——它需要在变量名上加一个$前缀,或者用另一种方法使其在函数作用域内可见——请参见this answer了解详细信息)。相反,将元音数组作为参数传递到函数中(并且可能在过程中对函数进行泛化),或者在函数内部硬编码它,因为我们可以假设元音不会改变。
在解决了范围问题之后,下一个问题是until是一个循环。一旦letter是一个辅音,它就会被反复推送到consonants数组中,直到程序内存耗尽。你可能是指unless。即使在这里,在找到元音时也需要breakreturn退出循环。
最后,有几个语义建议:vowels不是一个非常精确的函数名。它返回辅音,直到第一个元音,所以标题一样!参数“words”具有潜在的误导性,因为它表示一个数组或一系列单词,而您的函数似乎只对一个单词(或字符串)进行操作。
下面是一篇重述:
def front_consonants(word)
  vowels = "aeiou"
  consonants = []

  word.each_char do |letter|
    break if vowels.include? letter
    consonants << letter
  end

  consonants.join
end

p front_consonants "stack" # => "st"

10-08 04:27