【问题标题】:Why does my ruby pig latin translator not capitalize the first word of a string properly?为什么我的 ruby​​ pig 拉丁语翻译器不能正确大写字符串的第一个单词?
【发布时间】:2015-03-17 02:01:34
【问题描述】:

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

1) 以元音开头的单词应该只加上“ay”。

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

3) 以一个辅音开头的单词的常规猪拉丁语规则(即“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 是传入了猪拉丁化短语的数组。 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

而且,这是我在使用以下字符串运行测试时遇到的错误:“嗯,我有,甚至没有。看过那部电影。” (我明白标点符号没有意义)。

    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)>

【问题讨论】:

    标签: ruby capitalization punctuation


    【解决方案1】:

    很难调试虚构的代码。你在问人们为什么你的代码不提供一些关键变量的值就不能工作。

    她有一些建议:

    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() 不同)。这样您就不必在复杂的嵌套循环中搜索整个单词。请务必将 flag 变量设置回 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
    

    【讨论】:

    • 抱歉,您需要查看我的代码的哪一部分来调试它?但是,为了回应您的评论,如果它不包含 word[idx2],那么它不会继续下一次迭代直到找到大写字母吗?
    • @roonie,如果问题在我的回答中不明显,那么我需要查看uppercase_alphabet。我也想看看string
    • 对不起,string只是方法的参数:def translate(string)
    • @roonie,对于Quaint,我得到Uaintqay,所以您的代码只是将第一个字母Q 移到了末尾,而它本应将Qu 移到了末尾。
    • @roonie,您知道word[1..2].include?('qu') 检查字符串的第二个和第三个字符——而不是第一个和第二个字符吗?像数组这样的字符串从索引 0 开始。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    • 2014-06-08
    • 1970-01-01
    • 2020-05-11
    • 1970-01-01
    相关资源
    最近更新 更多