【问题标题】:How to capitalize first letter and lowercase the rest while keeping the word capital if it is in fully uppercase - java如果单词完全大写,如何在保持单词大写的同时将第一个字母大写并小写其余字母 - java
【发布时间】:2021-04-29 15:42:36
【问题描述】:
getSentenceCaseText()

以句子大小写返回当前文本的字符串表示形式。判例是 在句子中使用大写字母或仅将第一个字母大写的传统方式 词和任何专有名词。此外,所有大写单词应保持原样。

对于这个作业,名词仅限于以一个大写字母开头的单词。

**以字符串“First Sentence.secOND sentence.tHIRD SENTENCE”为例

它的输出将是(第一句。第二句。第三句)**


这是我完成上述任务的代码。我可以将每个点后的第一个字母大写并将其余字母设置为小写,但我不知道如何保持完整的大写单词。

下面是我的代码:

public String getSentenceCaseText(String text) { 
    
    int pos = 0;
    boolean capitalize = true;
    StringBuilder sb = new StringBuilder(text);
    
    while (pos < sb.length()){
         sb.setCharAt(pos, Character.toLowerCase(sb.charAt(pos)));
         if (sb.charAt(pos) == '.') {
            capitalize = true;      
        } else if (capitalize && !Character.isWhitespace(sb.charAt(pos))) {
            sb.setCharAt(pos, Character.toUpperCase(sb.charAt(pos)));   
            capitalize = false;
        }
        pos++;
       }   
   return sb.toString();
}
    

【问题讨论】:

    标签: java string split uppercase text-parsing


    【解决方案1】:

    您发布的大部分逻辑都可以正常工作。问题是 单词 像“SENTENCE”,因为您用来检查大小写的逻辑不正确。

    最大的问题是您试图遍历 单词 并同时检查该字符串是否大写。

    最简单的方法是分离关注点;尝试事先检查单词是否大写并采取相应措施。

    首先创建一个只检查 word 是否大写的方法。例如:

    public static boolean isUpper(String s, int start) {
        for(int i = start; i < s.length(); i++) {
            char c = s.charAt(i);
            if(c == '.' || c == ' ')
                return true;
            if (!Character.isUpperCase(c))
                return false;
        }
        return true;
    }
    

    此方法接收一个字符串(待检查)和一个int 值( start),该值告诉该方法应从字符串的哪个部分开始检查。 p>

    对于getSentenceCaseText 方法,请遵循以下策略。首先检查当前单词是否大写:

     boolean capitalize = isUpper(text, pos);
    

    如果是大写的,该方法应该跳过这个单词并移动到下一个单词。否则,它将第一个字符大写并降低其余字符。对文本中的所有单词应用相同的逻辑。

    代码可能如下所示:

    public static String getSentenceCaseText(String text) {
        int pos = 0;
        StringBuilder sb = new StringBuilder(text);
    
        // Iterate over the string
        while (pos < sb.length()){
            // First check if the word is capitalized 
            boolean capitalize = isUpper(text, pos);
            char c = sb.charAt(pos);
    
            // Make the first letter capitalized for the cases that it was not 
            sb.setCharAt(pos, Character.toUpperCase(c));
            pos++;
    
            // Let us iterate over the word
            // If it is not capitalized let us lower its characters
            // otherwise just ignore and skip the characters 
            for (;pos < sb.length() && text.charAt(pos) != '.' && text.charAt(pos) != ' '; pos++)
                if(!capitalize)
                    sb.setCharAt(pos, Character.toLowerCase(sb.charAt(pos)));
           
           // Finally we need to skip all the spaces
           for(; pos < sb.length() && text.charAt(pos) == ' '; pos++ );
        }
    
        return sb.toString();
    }
    

    使用此策略和此代码作为指导,在此基础上构建并实现您自己的方法。

    【讨论】:

      【解决方案2】:

      由于输入字符串可能包含多个句子,所以应该将其拆分为句子,然后将每个句子拆分为单词,所有大写的单词保持不变,句子中的第一个单词大写,其余单词大写变成小写了。

      可以使用正则表达式来完成split a string along with keeping delimiters

      static String capitalizeSentence(String input) {
          if (null == input || 0 == input.length()) {
              return input;
          }
      
          return Arrays
              .stream(input.split("((?<=[.!\\?]\\s?)|(?=[.!\\?]\\s?))"))
              .flatMap(sent -> { 
                  String[] words = sent.split("((?<=[^\\w])|(?=[^\\w]))"); 
                  return 
                      Stream.concat(
                          Stream.of(words[0].matches("[A-Z]+") // process first word
                              ? words[0] 
                              : (Character.toUpperCase(words[0].charAt(0)) + 
                                  (words[0].length() > 1 ? words[0].substring(1).toLowerCase() : ""))
                          ),
                          // process the rest of words
                          Arrays.stream(words)
                                .skip(1)
                                .map(word -> word.matches("[A-Z]+") ? word : word.toLowerCase())
                      );
              })
              .collect(Collectors.joining());
      }
      

      测试:

      System.out.println(capitalizeSentence("o! HI!first  SenTence. secOND  sentence. tHIRD: SENTENCE. am I OK?! yes, I am fine!!"));
      

      输出:

      O! HI!First  sentence. Second  sentence. Third: SENTENCE. Am I OK?! Yes, I am fine!!
      

      【讨论】:

        【解决方案3】:

        将问题拆分为较小的问题是一种很好的做法。所以我建议通过在“。”处分割文本来处理句子。并遍历句子。

        然后你通过在“”处拆分句子来处理每个句子的单词。

        然后检查每个单词,如果它完全是大写字母。如果是这样,保持不变。 如果不是,你检查一下,如果它是一个名词,这里的意思是,它有一个大写的第一个字母,其他没有大写字母。如果是,则保持不变,否则将其完全转换为小写。

        然后(作为最后一步)将每个句子的第一个单词的第一个字母大写。

        这样你就不需要任何全局标志了。您可以轻松地测试您的算法 - 用于单词和句子开头等特殊情况。如果您需要添加其他字符为“。”用于将文本拆分成句子 - 很简单。 如果您想对其他单词进行特殊处理 - 简单..

        【讨论】:

          【解决方案4】:

          你应该有一个布尔值 - isCapitalize

          一开始是真的。

          在迭代文本期间,您应该使用相同的词创建新的操作文本。

          如果isCapitalize 标志为真,则以第一个大写字母的方式写入单词。否则,用小写字母写。如果整个单词都有大写字母(这就是我们迭代单词的原因) - 正确的整个单词都是大写字母。

          如果您有“.”,则该标志仅显示 1 个字。

          现在把上面的文字写成代码。 如果您需要帮助,请告诉我们。

          【讨论】:

            【解决方案5】:

            设置第一个单词为大写,其余为小写

            String output = someString.substring(0, 1).toUpperCase() + someString.substring(1).toLowerCase(Locale.ROOT);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-11-29
              • 2017-06-20
              相关资源
              最近更新 更多