【问题标题】:What's the best way to check if a character is a vowel in Java?在 Java 中检查字符是否为元音的最佳方法是什么?
【发布时间】:2014-12-20 20:43:08
【问题描述】:

我正在尝试检查某个 char 是否是元音。这样做的最佳方法是什么?

【问题讨论】:

标签: java char string-parsing


【解决方案1】:

这是我已经使用了一段时间的解决方案,它还没有让我失望:

private static String VOWELS = "AÀÁÂÃÄÅĀĂĄǺȀȂẠẢẤẦẨẪẬẮẰẲẴẶḀÆǼEȄȆḔḖḘḚḜẸẺẼẾỀỂỄỆĒĔĖĘĚÈÉÊËIȈȊḬḮỈỊĨĪĬĮİÌÍÎÏIJOŒØǾȌȎṌṎṐṒỌỎỐỒỔỖỘỚỜỞỠỢŌÒÓŎŐÔÕÖUŨŪŬŮŰŲÙÚÛÜȔȖṲṴṶṸṺỤỦỨỪỬỮỰYẙỲỴỶỸŶŸÝ";
private static boolean isVowel(char c)
{
    return VOWELS.indexOf(Character.toUpperCase(c)) >= 0;
}

对于我的应用程序来说,它相当快。

【讨论】:

  • @Clashsoft 确保您使用 UTF-8 进行编译:javac "/path/to/your/file.java" -encoding UTF-8。也将其保存在没有 BOM 的 UTF-8 文件中。
  • 您的解决方案无法将“A”识别为元音,因为indexOf 返回0,但0 > 0 为假。
  • 谢谢@fredoverflow!
  • 很好的解决方案。很容易纠正的明显限制是它只处理西方脚本。更棘手的选择是,在某些语言中,同一个字母既可以是辅音也可以是元音,例如威尔士语中的 W
  • @diginoise 绝对正确!随意发布适合您情况的答案;它也可能对其他人有所帮助!
【解决方案2】:

创建一个 switch 语句。 例如:

switch (Character.toLowerCase(foo)) {
  case 'a':
  case 'e':
  case 'i':
  case 'o':
  case 'u':
  case 'y': return true;
  default: return false;
}

对于 Unicode,How do I detect unicode characters in a Java string? 遵循此处给出的答案,然后使用我提供的 switch 语句。

【讨论】:

  • 这是我一开始尝试的方法,但它在带有重音符号的字母上失败了,比如"café"'Æ',比如"Æther"
  • 啊。如果你想要 Unicode 字符,那么只需为它们添加大小写。此外,@Ben_Leggiero 的解决方案适用于 Unicode 字符。
  • 遗憾的是,unicode 没有元音的类或属性。这是有道理的,因为某些脚本(例如表意文字)并没有真正的元音概念。只要您有理由确定您认为元音是什么(例如,您可能会忽略日文假名),@BenLeggiero 的方法就可以了。
  • @BenLeggiero 看到这个问题:stackoverflow.com/questions/1008802/…。有几种可能的方法,但我没有尝试过。如果可行,您可以检查生成的字符是否为[aeiou]。 (您可能需要添加æ。)
【解决方案3】:

做到这一点的一种方法是使用 if-else 或 switch case,如@TylerWeaver 的回答。如果您想在一行中执行此操作,只需使用正则表达式

类似这样的:

元音:

aStr.matches("[aeiou]")

对于辅音:

aStr.matches("[^aeiou]")

正则表达式使生活变得非常简单,而且也相当容易学习。看看这个cheatsheet

在这种情况下,您只是创建了一个范围 [aeiou],这意味着您的角色必须匹配 aeiou[^aeiou] 是范围内未提及的所有字符。

【讨论】:

    【解决方案4】:

    我试图实现这一点,以涵盖尽可能多的语言,因为它们中包含类似元音的字母。据我统计,有 637 个 Unicode 字母可以算作元音。我有一个带有静态块的元音类,它设置了一个代表每个元音的字符串 HashSet。我使用一种假设代码点(int)而不是char的方法:

    public class Vowels {
    
      public Vowels() {
      }
    
      public static Set<String> vowelStrs;
    
      static {
        vowelStrs = new HashSet<String>();
        vowelStrs.add("A");
        vowelStrs.add("E");
        vowelStrs.add("I");
        ...
        vowelStrs.add("\u00c4");
        ...
        vowelStrs.add("\ua66b");
        vowelStrs.add("\ua66c");
        vowelStrs.add("\ua66d");
      }
    
      public boolean isMember(int inChar) {
        String inStr = new String(Character.toChars(inChar));
        return(Vowels.vowelStrs.contains(inStr));
      }
    }
    

    【讨论】:

    • 我喜欢使用集合的想法!
    • 在韩文和他加禄语使用者的帮助下,我现在实际上已经达到 800 多岁了。可能更好的解决方案是将此列表作为资源放入 UTF-8 文本文件中,然后从资源中加载到集合中。但是,文本编辑器有添加不受欢迎的字符/数据翻译的习惯(BOM、不理解 UTF-8 等)。这样,所有内容都是 7 位 ASCII,编译器将检查格式错误。
    • 这真是太棒了。当你有一个完整的列表并把它放在 GitHub 或其他东西上时让我知道:D
    • 您需要发布一个明确的 Unicode 元音列表,作为一项公共服务。 (对我没用,但我相信其他人会喜欢它!)
    • 另见...stackoverflow.com/questions/38792789/… 共识似乎是您的问题没有普遍的正确答案。为了满足您的需求,您需要研究或提供有关您的基本要求的更多信息。您想完成什么让您认为识别所有“UNICODE 元音字符”会帮助您做到这一点?
    【解决方案5】:

    根据公认的答案,这是一个最多需要 2 次有效表查找的解决方案:

    public static boolean isVowel(char c) {
        switch (c) {
            case 65:
            case 69:
            case 73:
            case 79:
            case 85:
            case 89:
            case 97:
            case 101:
            case 105:
            case 111:
            case 117:
            case 121:
            case 192:
            case 193:
            case 194:
            case 195:
            case 196:
            case 197:
            case 198:
            case 200:
            case 201:
            case 202:
            case 203:
            case 204:
            case 205:
            case 206:
            case 207:
            case 210:
            case 211:
            case 212:
            case 213:
            case 214:
            case 216:
            case 217:
            case 218:
            case 219:
            case 220:
            case 221:
            case 224:
            case 225:
            case 226:
            case 227:
            case 228:
            case 229:
            case 230:
            case 232:
            case 233:
            case 234:
            case 235:
            case 236:
            case 237:
            case 238:
            case 239:
            case 242:
            case 243:
            case 244:
            case 245:
            case 246:
            case 248:
            case 249:
            case 250:
            case 251:
            case 252:
            case 253:
            case 255:
            case 256:
            case 257:
            case 258:
            case 259:
            case 260:
            case 261:
            case 274:
            case 275:
            case 276:
            case 277:
            case 278:
            case 279:
            case 280:
            case 281:
            case 282:
            case 283:
            case 296:
            case 297:
            case 298:
            case 299:
            case 300:
            case 301:
            case 302:
            case 303:
            case 304:
            case 305:
            case 306:
            case 307:
            case 332:
            case 333:
            case 334:
            case 335:
            case 336:
            case 337:
            case 338:
            case 339:
            case 360:
            case 361:
            case 362:
            case 363:
            case 364:
            case 365:
            case 366:
            case 367:
            case 368:
            case 369:
            case 370:
            case 371:
            case 374:
            case 375:
            case 376:
            case 506:
            case 507:
            case 508:
            case 509:
            case 510:
            case 511:
            case 512:
            case 513:
            case 514:
            case 515:
            case 516:
            case 517:
            case 518:
            case 519:
            case 520:
            case 521:
            case 522:
            case 523:
            case 524:
            case 525:
            case 526:
            case 527:
            case 532:
            case 533:
            case 534:
            case 535:
                return true;
            default:
                switch (c) {
                    case 7680:
                    case 7681:
                    case 7700:
                    case 7701:
                    case 7702:
                    case 7703:
                    case 7704:
                    case 7705:
                    case 7706:
                    case 7707:
                    case 7708:
                    case 7709:
                    case 7724:
                    case 7725:
                    case 7726:
                    case 7727:
                    case 7756:
                    case 7757:
                    case 7758:
                    case 7759:
                    case 7760:
                    case 7761:
                    case 7762:
                    case 7763:
                    case 7794:
                    case 7795:
                    case 7796:
                    case 7797:
                    case 7798:
                    case 7799:
                    case 7800:
                    case 7801:
                    case 7802:
                    case 7803:
                    case 7833:
                    case 7840:
                    case 7841:
                    case 7842:
                    case 7843:
                    case 7844:
                    case 7845:
                    case 7846:
                    case 7847:
                    case 7848:
                    case 7849:
                    case 7850:
                    case 7851:
                    case 7852:
                    case 7853:
                    case 7854:
                    case 7855:
                    case 7856:
                    case 7857:
                    case 7858:
                    case 7859:
                    case 7860:
                    case 7861:
                    case 7862:
                    case 7863:
                    case 7864:
                    case 7865:
                    case 7866:
                    case 7867:
                    case 7868:
                    case 7869:
                    case 7870:
                    case 7871:
                    case 7872:
                    case 7873:
                    case 7874:
                    case 7875:
                    case 7876:
                    case 7877:
                    case 7878:
                    case 7879:
                    case 7880:
                    case 7881:
                    case 7882:
                    case 7883:
                    case 7884:
                    case 7885:
                    case 7886:
                    case 7887:
                    case 7888:
                    case 7889:
                    case 7890:
                    case 7891:
                    case 7892:
                    case 7893:
                    case 7894:
                    case 7895:
                    case 7896:
                    case 7897:
                    case 7898:
                    case 7899:
                    case 7900:
                    case 7901:
                    case 7902:
                    case 7903:
                    case 7904:
                    case 7905:
                    case 7906:
                    case 7907:
                    case 7908:
                    case 7909:
                    case 7910:
                    case 7911:
                    case 7912:
                    case 7913:
                    case 7914:
                    case 7915:
                    case 7916:
                    case 7917:
                    case 7918:
                    case 7919:
                    case 7920:
                    case 7921:
                    case 7922:
                    case 7923:
                    case 7924:
                    case 7925:
                    case 7926:
                    case 7927:
                    case 7928:
                    case 7929:
                        return true;
                }
        }
        return false;
    }
    

    嵌套开关对于保持案例密集并生成两个恒定时间tableswitch 指令是必要的。 在 535 和 7680 之间存在较大差距的单个开关将生成对数时间 lookupswitch 指令。

    【讨论】:

    • 为什么使用神秘数字而不是字符文字?
    • 对于字符文字,拆分为 2 个开关没有任何意义。
    • 你能详细说明一下吗?我对字节码了解不多
    • @Ben Leggiero 看看这个问题stackoverflow.com/questions/10287700/…
    • @Bharat 好的,我在那里阅读了答案,很清楚你为什么将它分成 2 个开关。我仍然不明白的是为什么您不使用字符文字; AFAIK 他们被编译成他们的 UTF-8 代码点,所以字节码是一样的,除非我弄错了。
    猜你喜欢
    • 2014-12-20
    • 2012-06-15
    • 2019-10-03
    • 2020-12-08
    • 1970-01-01
    • 2022-01-03
    • 2017-06-05
    • 1970-01-01
    • 2013-06-22
    相关资源
    最近更新 更多