为什么我的 ruby pig 拉丁语翻译器不能正确地将字符串的第一个单词大写?

Why does my ruby pig latin translator not capitalize the first word of a string properly?

我正在尝试编写一个程序,将带有一些大写单词和标点符号的字符串翻译成 Pig Latin。条件如下:

1) 以元音开头的单词应该放在 "ay" 上。

2) 以单个音素开头的单词,如 "sch" 或 "qu" 或 "squ" 或 "ch" 应该将所有这些字符移到末尾,而不仅仅是第一个字母,然后加上 "ay".

3) 以一个辅音开头的单词的常规 pig latin 规则(即 "Well," => 'Ellway,")。

4) 大小写和标点符号应该保留,但如果字母不是以元音开头,首字母会改变。所以 "Well," 会变成 "Ellway,".

一切正常,除了我的字符串的第一个单词。第四个条件永远不会满足字符串的第一个单词。因此,例如,"Well," 变为 "ellWay,"。所以标点符号有效,但大写字母不能正常工作。

编辑:我意识到只有当单词不是以元音开头时才会出现此问题。因此,"Actually," 变成了 "Actuallyay,"(应该是这样),但是 "Quaint," 变成了 "aintQuay,",而它应该是 "Aintquay,"。所以,这是我实际将拉丁猪传递到名为 pig_latin:

的数组中的代码
    string = string.split(' ')
    pig_latin = []
      string.each do |word|
      if vowels.include?(word[0])
        pig_latin << word + "ay"
      elsif (consonants.include?(word[0]) && consonants.include?(word[1]) && consonants.include?(word[2])) || word[1..2].include?('qu')
        pig_latin << (word[3..-1] + word[0..2] + "ay")
      elsif (consonants.include?(word[0]) && consonants.include?(word[1])) || word[0..1].include?('qu')
        pig_latin << (word[2..-1] + word[0..1] + "ay")
      else
        pig_latin << (word[1..-1] + word[0] + "ay")
      end
    end

这是我处理大写和标点符号的代码部分。澄清一下,pig_latin 是带有 pig-latinized 短语的数组。 uppercase_alphabet 是我创建的包含所有大写字母的数组:

    idx1 = 0
    while idx1 < pig_latin.count
      word = pig_latin[idx1]
      idx2 = 0
      while idx2 < word.length
        if uppercase_alphabet.include?(word[idx2])
            word[idx2] = word[idx2].downcase
            word[0] = word[0].upcase
        end

        if punctuation.include?(word[idx2])
            word[word.length], word[idx2] = word[idx2], ''
        end

        idx2 += 1
      end

      idx1 += 1
    end

pig_latin.join(' ')

编辑:这是概述我正在使用的各种数组的代码:

vowels = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']
lowercase_alphabet = ('a'..'z').to_a
uppercase_alphabet = ('A'..'Z').to_a
alphabet = lowercase_alphabet + uppercase_alphabet
punctuation = ['.', ',', ';', '?', '!', ':']
consonants = []
alphabet.each do |letter|
    consonants << letter unless vowels.include?(letter)
end

而且,这是我在 运行 使用以下字符串进行测试时遇到的错误:"Well, I have, not even. seen that movie."(我知道标点符号没有意义)。

    1) #translate retains punctuation from the original phrase
    Failure/Error: s.should == "Ellway, Iay avehay, otnay evenay.  eensay atthay oviemay."

        expected: "Ellway, Iay avehay, otnay evenay. eensay atthay oviemay."

        got: "ellWay, Iay avehay, otnay evenay. eensay atthay oviemay." (using ==)

        # ./spec/04_pig_latin_spec.rb:83:in `block (2 levels) in <top (required)>

虚代码难调试。您在问人们为什么您的代码在不提供某些关键变量的值的情况下无法运行。

她有一些提示:

1) 字符串就像数组一样工作,因此您不必创建 单个字母数组,强制您键入所有逗号和引号:

vowels = 'aeiou'

vowels.include?('a')  #=>true

2) 您不必在辅音和元音数组中包含大写字母,而是可以在调用 include?():

 ch = 'A'
 vowels.include?(ch.downcase)  #=> true

3) 在调试时,putsp(对于数组、哈希)是你的朋友。您可以通过添加 puts/p 语句找出正在执行的 elsif 分支:

  if vowels.include?(word[0])
    puts 'X'
    pig_latin << word + "ay"
  elsif (consonants.include?(word[0]) && consonants.include?(word[1]) && consonants.include?(word[2])) || word[1..2].include?('qu')
    puts 'A'
    pig_latin << (word[3..-1] + word[0..2] + "ay")
  elsif (consonants.include?(word[0]) && consonants.include?(word[1])) || word[0..1].include?('qu')
    puts 'B'
    pig_latin << (word[2..-1] + word[0..1] + "ay")
  else
    puts 'C'
    pig_latin << (word[1..-1] + word[0] + "ay")
  end
end

4) 比较字符串时,可以使用==。而不是这个:

word[0..1].include?('qu')

...你可以这样写:

if word[0..1].downcase == 'qu'

尽可能使用 == 效率更高。

5) 你的 if 条件太复杂了。如果你知道正则表达式是什么,你可以通过提取单词开头的辅音来简化事情,然后使用 if 语句来测试辅音是什么:

words = %w{
  schlepp
  quail
  squall
  checkers
}

consonants = ('a'..'z').to_a.join.tr('aeiou', '')

words.each do |word|
  md = word.match(/
        \A                 #match start of string, followed by...
        [#{consonants}]+   #a consonant, 1 or more times
  /x)

  if md
    starting_consonants = md[0]

    #Test for starting_consonants here, e.g.
    #if starting_consonants == 'q' and word[1] == 'u'
    #   do something
  else  #then word starts with a vowel
    ...
  end
end

--output:--
schl
q
sq
ch

您可以像这样将提取的辅音数量限制为三个:

[#{consonants}]{1,3}

6) 我会在您更改单词的同时处理大写——这样您就不必搜索每个单词中的所有字母。首先,检查第一个字母的大小写(然后设置一个标志变量,例如 capitalized = true)。然后小写第一个字母。然后在你改变单词后,如果有大写,将第一个字母大写(你也可以调用 capitalize(),但结果可能与只在第一个字母上调用 upcase() 不同)。这样您就不必在复杂的嵌套循环中搜索整个单词。请务必将标志变量设置回 false。

7) 在 ruby 中,您很少使用 while 循环并递增计数器:

while idx2 < word.length
  char = word[idx2]
  ...
  ...
  idx2 += 1
end

相反,您使用 each() 循环:

   word.each_char do |char|
     #do something with char

   end