【问题标题】:Polishing my Pig Latin translator (Code) (Java)抛光我的 Pig 拉丁语翻译器(代码)(Java)
【发布时间】:2012-12-10 10:19:08
【问题描述】:

我在这里的任务是使用递归创建一个猪拉丁语翻译器,它可以翻译句子。规则如下:

  1. 如果englishWord 中没有元音,那么pigLatinWord 就是englishWord + "ay"。 (有十个元音:'a'、'e'、'i'、'o' 和 'u',以及它们的对应大写字母。就本作业而言,'y' 不被视为元音,即my 变成 myay,why 变成 whyay 等等)
  2. 否则,如果englishWord 以元音开头,那么pigLatinWord 就是englishWord + "yay"。
  3. 否则(如果englishWord 中有元音但不以元音开头),则pigLatinWord 为end + start + "ay",其中end 和start 定义如下: -

让 start 是所有英语单词,直到(但不包括)它的第一个元音。 让 end 成为从第一个元音开始的所有英语单词。 但是,如果 englishWord 大写,则 end 大写,“uncapitalize”开始。

到目前为止,这是我的代码(对不起,奇怪的格式,我的 cmets 搞砸了):

    /*Recursively Translate a String (without punctuation or numerical characters) to Pig Latin*/


//prep the string for translation and submit it to be translated
public static String translate(String finished) {
    finished.trim();        //Trim the String of whitespace at the front and end
    finished += " ";        //Because of the recursive method I use, the string must have a
                            //space at the end
    finished = translateSentence(finished); //recursively translate the string
    finished.trim();    //trim the whitespace added earlier
    return finished;    //Return the string
}


//recursively submits each word in the string to the translator, then 
//returns the translated sentence
private static String translateSentence(String finished) {

if (finished.length() == 0) {   //the base condition is met when each word in the string
   return finished; //has been sent to the translator (string is empty)
    }
    else {
    return (translateWord(finished.substring(0, finished.indexOf(' ') )) + " "
        + translateSentence(finished.substring(finished.indexOf(' ') + 1)));        
    }
}
/*If the base condition is not met, the method returns the first word of the string
 * (translated) and a space, then submits the rest of the 
 * string back to the method.  The first word is defined as the beginning 
 * of the string up until the first space. The rest of the string
 * starts one character after the space.   */



//Checks the submitted word for vowels and vowel placement, and translates accordingly

    private static String translateWord(String stringA) {
    if (stringA.indexOf('a') == -1
    && stringA.indexOf('e') == -1           //Checks for presence of any vowels
    && stringA.indexOf('i') == -1       //if no vowels are found
    && stringA.indexOf('o') == -1       //the word + ay is returned
    && stringA.indexOf('u') == -1
    && stringA.indexOf('A') == -1
    && stringA.indexOf('E') == -1
    && stringA.indexOf('I') == -1
    && stringA.indexOf('O') == -1
    && stringA.indexOf('U') == -1) {
        return stringA + "ay";
    }       
    if (stringA.charAt(0) == 'a'
    ||  stringA.charAt(0) == 'e' //checks if there is a vowel at the start
    ||  stringA.charAt(0) == 'i'//of the string. if there is a vowel
    ||  stringA.charAt(0) == 'o'    //it returns the word + yay
    ||  stringA.charAt(0) == 'u'
    ||  stringA.charAt(0) == 'A'
    ||  stringA.charAt(0) == 'E'
    ||  stringA.charAt(0) == 'I'
    ||  stringA.charAt(0) == 'O'
    ||  stringA.charAt(0) == 'U') {
        return stringA + "yay";
    }       
/* if the word has a vowel that isn't at the start, the part of the string


* before the first vowel is moved to the end of the vowel, and "ay" is added.


* However, if the first character in the word is capitalized, the first vowel becomes


* uppercase and the former first character in the word becomes lowercase */
    else {
        if (Character.isUpperCase(stringA.charAt(0))) {
            return Character.toUpperCase(stringA.charAt(firstVowel(stringA, 0))) 
            + stringA.substring(firstVowel(stringA, 0) + 1, stringA.length())
            + Character.toLowerCase(stringA.charAt(0))
            + stringA.substring(1, firstVowel(stringA, 0)) + "ay";
        }
        else {
        return stringA.substring(firstVowel(stringA, 0), stringA.length()) 
        + stringA.substring(0, firstVowel(stringA, 0)) + "ay";
        }
    }
}



//Recursively determines the index number of the first vowel in a given word
//0 must always be submitted as int x
public static int firstVowel(String stringA, int x) {
    if (x > stringA.length() - 1) {     //if the index number becomes greater than the length
        return -1;      //of the string, -1 (no vowels) is returned
    }
    if (stringA.charAt(x) == 'a' 
        || stringA.charAt(x) == 'e'     //the base condition is met when the character
        || stringA.charAt(x) == 'i'     //at the current index number is a vowel
        || stringA.charAt(x) == 'o'     //and the index number is returned
        || stringA.charAt(x) == 'u' 
        || stringA.charAt(x) == 'A' 
        || stringA.charAt(x) == 'E' 
        || stringA.charAt(x) == 'I' 
        || stringA.charAt(x) == 'O' 
        || stringA.charAt(x) == 'U') {
        return x;
    }
    else {
        return firstVowel(stringA, x + 1);  //otherwise, the string and the index number
    }                                       // + 1 are submitted back to the method
}

这给了我想要的输出(“Why hello there”变成了“Whyay ellohay erethay”) 但现在它无法处理标点符号。基本上我正在寻找的是任何提示或帮助让我的代码处理标点符号,或任何改进我的代码的方法(仍然使用递归)。

【问题讨论】:

  • 一项改进是将所有元音放在一个字符串常量中,并使用contains() 来检查一个字符是否为元音。此外,firstVowel(stringA, 0) 可以提取到局部变量中,这将进一步提高可读性。
  • 你能澄清一下关于 contains() 方法的部分吗?我真的不明白如何将字符串常量 contains() 和我正在检查的字符串联系起来。谢谢。
  • 我的意思是这样的:private static final String VOWELS = "aeiouAEIOU";,然后当您检查元音时,您会使用private static boolean isVowel( char ch ) { return VOWELS.contains( String.valueOf( ch ) ); }。它比 if 大声明更容易阅读。

标签: java


【解决方案1】:

@Cedric 给出了一个很好的建议,可以在处理过程中使用正则表达式。

这里我给出一些其他的指示。

首先,我相信您可以更好地重用您的 firstVowel 方法。

您的translateWord 可以大大简化为(我跳过您的大写处理以便更容易理解):

private static String translateWord(String s) {
    int firstVowelIndex = firstVowel(s);
    if (firstVowel < 0) { // no Vowel
        return s + "ay";
    } else if (firstVowel == 0) {  // start with Vowel
        return s + "yay";
    } else {
        return s.substring(firstVowelIndex) + s.substring(0, firstVowelIndex) + "ay";
    }
}

您的firstVowel() 中也有一些需要简化的内容。

首先可以简化元音的比较。一种方法是使用正则表达式。另一种方法是使用 Set:

假设你有这样的东西:

static Set<Character> vowels = new HashSet<Character>(
        Arrays.asList('a','e','i','o','u','A','E','I','O','U'));

然后你的元音检查可以从长 if 语句更改为:

if (vowels.contains(c)) {...}

其次,您可能故意以递归方式编写 firstVowel() 以进行练习。但是,在我看来,如果以循环的形式编写该方法,则更容易阅读:

private static int firstVowel(String s) {
    int index = -1;
    for (int i = 0; i < s.length; ++i ) {
        if (isVowel(s.charAt(i)) {
            index = i;
            break;
        }
    }
    return index;
}

我相信这两项更改几乎可以以更易读的方式将您的代码减半。

【讨论】:

    【解决方案2】:

    尝试使用正则表达式来匹配您的单词。正则表达式 [a-zA-Z]+ 将匹配任何同时出现的字母序列。关于如何在 java 中使用正则表达式,我将把它作为练习留给你,但这并不难。

    基本上取你的字符串,找到下一个匹配。存储单词的最后一个字符在原始字符串中的位置。处理该单词,然后找到下一个匹配项。现在取上一个匹配的最后一个字符和当前匹配的第一个字符之间的子串,原样输出,不做任何处理。

    示例:假设我有字符串“Hello, world!”

    • 第一个匹配项是“Hello”,从位置 0 开始,到位置 4(含)结束。
    • 处理并输出“Ellohay”
    • 查找下一个匹配项,即“world”,从位置 7 开始,到位置 11 结束
    • 输出上一个匹配的最后一个字符和当前匹配的第一个字符之间的子字符串。这意味着从位置 5 到位置 6,这给出了字符串 ", "
    • 处理当前匹配并输出。这将输出“orldway”
    • 尝试查找下一个匹配项。现在找不到匹配项
    • 输出字符串的其余部分而不进行任何处理。这意味着从位置 12 到字符串的末尾。这给出了子字符串“!”

    通过这种方式,该过程将转换“Hello, world!”到“Ellohay,orldway!”

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 2013-08-08
      • 2020-12-20
      • 1970-01-01
      • 2020-05-11
      • 2018-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多