【问题标题】:Can I improve this Pig-Latin converter? [closed]我可以改进这个 Pig-Latin 转换器吗? [关闭]
【发布时间】:2010-08-03 18:26:33
【问题描述】:

我是 Java 新手,我为 PigLatin 制作了这个小翻译器。

package stringmanipulation;

public class PigLatinConverter {
    public String Convert(String word){
        int position = 0;
        if (!IsVowel(word.charAt(0))) {
            for (int i= 0; i < word.length(); i++) {
                if (IsVowel(word.charAt(i))) {
                    position = i;
                    break;
                }
            }
            String first = word.substring(position, word.length());
            String second = word.substring(0, position) + "ay";

            return first + second;
        } else {
            return word + "way";
        }
    }

    public boolean IsVowel(char c){
        if (c == 'a')
            return true;
        else if(c == 'e')
            return true;
        else if(c == 'i')
            return true;
        else if(c == 'o')
            return true;
        else if(c == 'u')
            return true;
        else
            return false;        
    }
}

有什么可以改进的吗?

在我可能不知道的最新 Java 版本中是否有任何漂亮的 Java 技巧?我来自 C# 背景。

谢谢!

【问题讨论】:

  • 请不要删除 piglatin 标签,它与问题有关。
  • 我不同意,标签piglatin 完全无关紧要,但我会让你安心。
  • 这类问题属于code review
  • piglatin 标签与 Apache Pig 的语言层有关。通过阅读标签的定义,您会发现它与 Java 中的字符串操作无关。

标签: java string substring translation


【解决方案1】:

我将isVowel(char ch) 改写如下:

return "aeiou".indexOf(ch) != -1;

我会改写以下内容:

// String first = word.substring(position, word.length());
   String first = word.substring(position);

我还会重命名方法名称以遵循编码约定。

当然,作为我,我也会使用正则表达式而不是 substringfor 循环。

System.out.println("string".replaceAll("([^aeiou]+)(.*)", "$2$1ay"));
// ingstray

参考文献

【讨论】:

  • 这就是我一直在寻找的性感。我会测试一下。编辑:我收到一个错误:必需:找到 CharSequence:Char
  • @Sergio:抱歉,请改用indexOf(char)
  • +1 表示“作为我,我也会使用正则表达式”(当然还有其他答案)。让我发笑。
【解决方案2】:

免责声明:我不懂 Java。

倒置的逻辑令人困惑,请这样写你的if 语句:

    if (IsVowel(word.charAt(0))) {
        return word + "way";
    } else {
        for (int i= 0; i < word.length(); i++) {

        // ...

        return first + second;
    }

您甚至可以删除else

IsVowel 可能需要保密。它也可以使用单个|| 链或"".indexOf(或Java 中的任何内容)重写。

您的for 逻辑可以简化为简短的while

        while (position < word.length() && !IsVowel(word.charAt(position)) {
            ++position;
        }

【讨论】:

  • 我同意倒转逻辑。在我看来,while 语句似乎有点令人费解。
  • @Sergio Tapia,Java 可能有类似.indexOf 的东西,它接受一个回调作为参数(你会使用IsVowel 作为回调),它将循环变成一个调用和一个检查。
  • 非常更喜欢“早点回来”;更多级别的缩进使代码更难阅读。显然,嵌套条件也是 bug 的主要来源。
  • @tc.,虽然我同意,但我发现这是更个人化的风格,而不是目标。 (参见:single-return-per-function 倡导者。)
  • 大概是那些认为“goto”总是邪恶的人,而我认为不必要地将流控制嵌入到您的数据中是邪恶的(并且对您的编译器进行优化很痛苦)。
【解决方案3】:

如果你知道如何阅读正则表达式,这里有一个完整的重写,它使代码更具可读性:

String[] words =
    "nix scram stupid beast dough happy question another if".split(" ");

for (String word : words) {
    System.out.printf("%s -> %s%n", word,
        ("w" + word).replaceAll(
            "w(qu|[^aeiou]+|(?<=(w)))([a-z]*)",
            "$3-$1$2ay"
        )
    );
}

这会打印 (as seen on ideone.com):

nix -> ix-nay
scram -> am-scray
stupid -> upid-stay
beast -> east-bay
dough -> ough-day
happy -> appy-hay
question -> estion-quay
another -> another-way
if -> if-way

注意question变成estion-quay,这是根据Wikipedia article的正确翻译。其实上面的文字和译文都是取自文章。

正则表达式的工作方式如下:

  • 首先,所有单词都以w为前缀,以防万一
  • 然后,跳过w,查找qu 或非空的辅音序列。如果两者都找不到,则实际单词以元音开头,因此使用后向捕获获取w
  • 然后只需重新排列组件即可获得翻译

即:

"skip" dummy w
|
w(qu|[^aeiou]+|(?<=(w)))([a-z]*)   -->  $3-$1$2ay
 \                2\_/ /\______/
  \_________1_________/    3

参考文献

【讨论】:

  • 我开始在您的答案中看到 ASCII 艺术,在这个中看到一辆颠倒的卡车 :) 艺术 +1。
【解决方案4】:

我知道这个问题已经有一年多了,但我想我会修改它。这段代码有几处改进。

public String convert(String word)
{
    int position = 0;
    while(!isVowel(word.charAt(position)))
    {
        ++position;
    }
    if(position == 0)
    {
        return word + "-way";
    }
    else if(word.charAt(0) == 'q')
    {
        ++position;
    }
    return word.substring(position) + "-" + word.substring(0, position) + "ay";
}
public boolean isVowel(char character) 
{
    switch(character)
    {
        case 'a': case 'e': case 'i': case 'o': case 'u':
            return true;
        default:
            return false;
    }
}

首先代码会找到第一个元音的位置,然后跳出循环。这比使用 for 循环遍历每个字母并使用 break 更简单;跳出循环。其次,这将匹配维基百科网站上的所有测试用例。最后,由于 chars 实际上是有限范围的 int,因此可以使用 switch 语句来提高性能和可读性。

【讨论】:

    【解决方案5】:

    严格来说并不是这样的改进,但 Java 约定规定方法应以小写字母开头。

    【讨论】:

    • Sergio 似乎是个 C# 人。讨厌的人会讨厌。
    • 我不是讨厌,我真的很想学习Java。 :)
    【解决方案6】:

    我已经离开 Java 多年了,但总的来说,您的代码看起来不错。如果你想挑剔,这里有一些 cmets:

    • 添加 cmets。它不必遵循 Javadoc 规范,但至少明确描述接受的参数和预期的返回值,并可能给出一些关于它如何工作的提示(根据第一个字符是否为元音而表现不同)
    • 您可能想要捕获IndexOutOfBoundsException,我认为如果您将零长度字符串传递给它可能会发生这种情况。
    • 方法名称应为小写。
    • IsVowel 可以重写 return c == 'a' || c == 'e' 等等。由于短路,比较次数方面的性能应该相似。

    【讨论】:

      【解决方案7】:

      这是作业吗?如果是这样,请将其标记为这样。

      • 不清楚“诚实”或“镱”的预期行为是什么。
      • 它不尊重大写字母(“Foo”应该变成“Oofay”,AEIOU也是元音)。
      • 如果你传入空字符串,它会崩溃。

      【讨论】:

        猜你喜欢
        • 2021-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-02
        • 1970-01-01
        • 2016-01-13
        • 1970-01-01
        相关资源
        最近更新 更多