Java 将单词格式化成句子

Java 将单词格式化成句子,java,Java,完成该方法,以便将单词格式化为单个逗号分隔的值。最后一个单词应该用“and”而不是逗号分隔。应忽略空字符串值。传递到方法中的空数组或null/nil值应导致返回空字符串 例如: {"ninja", "samurai", "ronin"}) => "ninja, samurai and ronin" {"ninja", "", "ronin"}) => "ninja and ronin" 代码 如何删除最后一个逗号?一种常见的方法是引入分隔符变量。在第一次迭代中它是空字符串,然后大部

完成该方法,以便将单词格式化为单个逗号分隔的值。最后一个单词应该用“and”而不是逗号分隔。应忽略空字符串值。传递到方法中的空数组或null/nil值应导致返回空字符串

例如:

{"ninja", "samurai", "ronin"}) => "ninja, samurai and ronin"
{"ninja", "", "ronin"}) => "ninja and ronin"
代码


如何删除最后一个逗号?

一种常见的方法是引入分隔符变量。在第一次迭代中它是空字符串,然后大部分时间它是空字符串,在最后一次迭代中它是和

在重复追加字符串时使用StringBuilder也是最佳做法,以避免重复浪费内存分配

public static String formatWords(String[] words) {
    if (words == null || words.length == 0) {
        return "";
    }
    StringBuilder ans = new StringBuilder();
    for (int i = 0; i < words.length; i++) {
        String sep = ", ";
        if (i == 0)
            sep = "";
        else if (i == words.length - 1)
            sep = " and ";
        ans.append(sep).append(words[i]);
    }
    return ans.toString();
}

一种常见的技术是引入分隔符变量。在第一次迭代中它是空字符串,然后大部分时间它是空字符串,在最后一次迭代中它是和

在重复追加字符串时使用StringBuilder也是最佳做法,以避免重复浪费内存分配

public static String formatWords(String[] words) {
    if (words == null || words.length == 0) {
        return "";
    }
    StringBuilder ans = new StringBuilder();
    for (int i = 0; i < words.length; i++) {
        String sep = ", ";
        if (i == 0)
            sep = "";
        else if (i == words.length - 1)
            sep = " and ";
        ans.append(sep).append(words[i]);
    }
    return ans.toString();
}

如果您使用的是Java 8,解决方案可以简化如下:

public static String formatWords(String[] words) {
    String res = Arrays.asList(words)
          .stream()
          .filter(word -> !(word == null))
          .filter(word -> !word.equals(""))
          .collect(Collectors.joining(","));
    if(! res.contains(","))
        return res;

    int indexOfLastComma = res.lastIndexOf(",");

    String resultuntilLastWord = res.substring(0, indexOfLastComma);
    String lastWord = res.substring(indexOfLastComma + 1);

    res = resultuntilLastWord + " and " + lastWord;
    return res;
}
首先在代码中构造一个结果字符串res,所有分隔符都是逗号

然后,获取字符串中最后一个逗号的索引并创建两个子字符串。一个子字符串应一直保留到字符串中的最后一个逗号:

String resultuntilLastWord = res.substring(0, indexOfLastComma);
其他的应该一直到字符串的末尾:

String lastWord = res.substring(indexOfLastComma + 1);

最后用and将这两个子字符串合并在一起。

如果您使用的是Java 8,解决方案可以简化如下:

public static String formatWords(String[] words) {
    String res = Arrays.asList(words)
          .stream()
          .filter(word -> !(word == null))
          .filter(word -> !word.equals(""))
          .collect(Collectors.joining(","));
    if(! res.contains(","))
        return res;

    int indexOfLastComma = res.lastIndexOf(",");

    String resultuntilLastWord = res.substring(0, indexOfLastComma);
    String lastWord = res.substring(indexOfLastComma + 1);

    res = resultuntilLastWord + " and " + lastWord;
    return res;
}
首先在代码中构造一个结果字符串res,所有分隔符都是逗号

然后,获取字符串中最后一个逗号的索引并创建两个子字符串。一个子字符串应一直保留到字符串中的最后一个逗号:

String resultuntilLastWord = res.substring(0, indexOfLastComma);
其他的应该一直到字符串的末尾:

String lastWord = res.substring(indexOfLastComma + 1);
最后用and将这两个子字符串合并在一起。

您可以使用逗号创建字符串。然后用正则表达式替换最后一个逗号

String[] values = {"ninja", "samurai", "ronin"};

//Join each values with ", "
String phrase = String.join(", ", values);
System.out.println(phrase); //ninja, samurai, ronin

//Replace the last "," with " and"
phrase = phrase.replaceFirst(",([^,]+)$", " and$1");
System.out.println(phrase); //ninja, samurai and ronin
这是在一行中完成的:

String phrase = String.join(", ", values).replaceFirst(",([^,]+)$", " and$1");
当可以看到结果时,使用快速测试方法:

public static String createPhrase(String[] values){
    return String.join(", ", values).replaceFirst(",([^,]+)$", " and$1");
}

System.out.println(createPhrase(new String[] {"ninja"} ));
System.out.println(createPhrase(new String[] {"ninja", "samurai"}));
System.out.println(createPhrase(new String[] {"ninja", "samurai", "ronin"}));
忍者 忍者与武士 忍者、武士和浪人

注:

要管理数组中的空值和空值,最简单的方法是使用流

然后使用相同的正则表达式来管理和部分。

您可以使用它创建带有逗号的字符串。然后用正则表达式替换最后一个逗号

String[] values = {"ninja", "samurai", "ronin"};

//Join each values with ", "
String phrase = String.join(", ", values);
System.out.println(phrase); //ninja, samurai, ronin

//Replace the last "," with " and"
phrase = phrase.replaceFirst(",([^,]+)$", " and$1");
System.out.println(phrase); //ninja, samurai and ronin
这是在一行中完成的:

String phrase = String.join(", ", values).replaceFirst(",([^,]+)$", " and$1");
当可以看到结果时,使用快速测试方法:

public static String createPhrase(String[] values){
    return String.join(", ", values).replaceFirst(",([^,]+)$", " and$1");
}

System.out.println(createPhrase(new String[] {"ninja"} ));
System.out.println(createPhrase(new String[] {"ninja", "samurai"}));
System.out.println(createPhrase(new String[] {"ninja", "samurai", "ronin"}));
忍者 忍者与武士 忍者、武士和浪人

注:

要管理数组中的空值和空值,最简单的方法是使用流


然后使用相同的正则表达式来管理和部分。

一个简单的解决方案是按降序运行循环。我对你的代码做了一些修改。。希望如此

public static String formatWords(String[] words)
{
    Vector<String> v= new Vector<String>();
    if (words == null || words.length == 0)
        return "";

    for (int i = 0; i < words.length; i++)
        if (!words[i].equals("")) v.add(words[i]);

    String str="";
    for (int i = v.size()-1; i >= 0; i--)
    {
        if(str.equals("")){
            if(i>0)
                str = " and " + v.get(i);
            else
                str = v.get(i);
        }else{
            if(i==0)
                str = v.get(i) + str;
            else
                str = "," + v.get(i) + str;
        }
    }
    return str;
}

编辑:为解决评论中提到的问题@AJNeufeld添加了一个修正向量。

一个简单的解决方案是按降序运行循环。我对你的代码做了一些修改。。希望如此

public static String formatWords(String[] words)
{
    Vector<String> v= new Vector<String>();
    if (words == null || words.length == 0)
        return "";

    for (int i = 0; i < words.length; i++)
        if (!words[i].equals("")) v.add(words[i]);

    String str="";
    for (int i = v.size()-1; i >= 0; i--)
    {
        if(str.equals("")){
            if(i>0)
                str = " and " + v.get(i);
            else
                str = v.get(i);
        }else{
            if(i==0)
                str = v.get(i) + str;
            else
                str = "," + v.get(i) + str;
        }
    }
    return str;
}

编辑:为解决评论中提到的问题@AJNeufeld添加了一个向量,我觉得这是一个家庭作业,所以我不会给你完整的解决方案,但我会给你指出正确的方向,而不使用ArrayList、Vector、Stream等高级概念。of。。。还有正则表达式,可能还没有教过

此赋值中最大的挑战是正确跳过单词数组中的null/nil值,仍然为逗号分隔符和final and分隔符找到正确的位置。在单词数组上循环时,i==0项不一定标记第一个实单词,因为数组可能以null或空字符串开头。类似地,i==words.length-1条目不一定代表最后一个单词,因为数组可能以null或空字符串结尾。这意味着循环索引i对于确定是否需要分隔符以及使用哪个分隔符实际上是无用的

由于循环索引或多或少是无用的,我们可以使用增强的for循环构造来循环数组中的字:

for(String word : words) {
    // ... code here
}
如果您尚未学习增强型for循环,则可以坚持使用:

for(int i = 0; i < words.length; i++) {
    String word = words[i];
    // ... code here
}
通过知道有numWords单词,您现在可以明确地说and分隔符位于最后一个单词之前,从numWords的第1个单词开始计算

考虑到这一点,您现在可以执行第二个循环,该循环查看每个单词,并决定是否将其视为有效单词,并仅为有效单词更新wordNumber

String result = "";
int wordNumber = 0;
for(String word : words) {
    if (words != null  &&  !word.isEmpty()) {
        wordNumber++;

        // If not the first word, then add a separator (either a 
        // comma or the word "and" if at the last word) to result.
        // Then, add word to result.
    }
}
在添加单词和适当分隔符的最后一步中,我省略了实际代码。这与OP在解决问题的初始尝试中所做的没有太大区别,因此应该清楚地知道如何继续,但这不是从堆栈溢出复制粘贴的解决方案。这个学生在lea学习 这是一些工作

上述解决方案使用两个for循环;第一个用于计算有效单词的数量,第二个用于处理单词。通常最好只循环一次数据。这允许您处理数据流,其中数据是暂时的或短暂的,您可能没有第二次机会读取数据

显然,本例中的情况并非如此。数据在一个数组中;您可以在数据上循环任意次数。但是仍然可以只使用一个循环来执行操作

使用一个循环处理数据更为复杂。诀窍是保留最新的单词,并延迟将其添加到结果中,直到您知道要使用哪个分隔符(如果有的话)将其添加到结果中。当你完成所有单词的循环后,你将得到一个部分结果,以及最近的一个单词,也就是最后一个单词。在这一点上,你只需将最后一个词添加到结果中,加上连接词和,除非它也是第一个词

String result = "";

String most_recent_word = null;
for(String word : words) {
    if (word != null  &&  !word.isEmpty()) {
        if (most_recent_word != null) {
           // Add most_recent_word to result, preceded by a comma if necessary
        }
        most_recent_word = word;
    }
}

if (most_recent_word != null) {
    // Add most_recent_word to result, preceded by " and " if necessary
}
同样,我省略了确定是否需要分隔符的关键代码,并将其和最新单词添加到结果中。再次,留给学生,以避免复制和粘贴从堆栈溢出的家庭作业解决方案


正如其他地方提到的,使用StringBuilder构建最终字符串可以提高上述两种解决方案的代码效率。它不是必需的,但如果你已经学会如何使用它,你应该使用它

我觉得这是一个家庭作业,所以我不会给你完整的解决方案,但我会给你指出正确的方向,而不使用先进的概念,如ArrayList、Vector、Stream。of。。。还有正则表达式,可能还没有教过

此赋值中最大的挑战是正确跳过单词数组中的null/nil值,仍然为逗号分隔符和final and分隔符找到正确的位置。在单词数组上循环时,i==0项不一定标记第一个实单词,因为数组可能以null或空字符串开头。类似地,i==words.length-1条目不一定代表最后一个单词,因为数组可能以null或空字符串结尾。这意味着循环索引i对于确定是否需要分隔符以及使用哪个分隔符实际上是无用的

由于循环索引或多或少是无用的,我们可以使用增强的for循环构造来循环数组中的字:

for(String word : words) {
    // ... code here
}
如果您尚未学习增强型for循环,则可以坚持使用:

for(int i = 0; i < words.length; i++) {
    String word = words[i];
    // ... code here
}
通过知道有numWords单词,您现在可以明确地说and分隔符位于最后一个单词之前,从numWords的第1个单词开始计算

考虑到这一点,您现在可以执行第二个循环,该循环查看每个单词,并决定是否将其视为有效单词,并仅为有效单词更新wordNumber

String result = "";
int wordNumber = 0;
for(String word : words) {
    if (words != null  &&  !word.isEmpty()) {
        wordNumber++;

        // If not the first word, then add a separator (either a 
        // comma or the word "and" if at the last word) to result.
        // Then, add word to result.
    }
}
在添加单词和适当分隔符的最后一步中,我省略了实际代码。这与OP在解决问题的初始尝试中所做的没有太大区别,因此应该清楚地知道如何继续,但这不是从堆栈溢出复制粘贴的解决方案。这个学生至少做了一些工作

上述解决方案使用两个for循环;第一个用于计算有效单词的数量,第二个用于处理单词。通常最好只循环一次数据。这允许您处理数据流,其中数据是暂时的或短暂的,您可能没有第二次机会读取数据

显然,本例中的情况并非如此。数据在一个数组中;您可以在数据上循环任意次数。但是仍然可以只使用一个循环来执行操作

使用一个循环处理数据更为复杂。诀窍是保留最新的单词,并延迟将其添加到结果中,直到您知道要使用哪个分隔符(如果有的话)将其添加到结果中。当你完成所有单词的循环后,你将得到一个部分结果,以及最近的一个单词,也就是最后一个单词。在这一点上,你只需将最后一个词添加到结果中,加上连接词和,除非它也是第一个词

String result = "";

String most_recent_word = null;
for(String word : words) {
    if (word != null  &&  !word.isEmpty()) {
        if (most_recent_word != null) {
           // Add most_recent_word to result, preceded by a comma if necessary
        }
        most_recent_word = word;
    }
}

if (most_recent_word != null) {
    // Add most_recent_word to result, preceded by " and " if necessary
}
同样,我省略了确定是否需要分隔符的关键代码,并将其和最新单词添加到结果中。再次,留给学生,以避免复制和粘贴从堆栈溢出的家庭作业解决方案


正如其他地方提到的,使用StringBuilder构建最终字符串可以提高上述两种解决方案的代码效率。它不是必需的,但如果你已经学会如何使用它,你应该使用它

建议:阅读你的帖子,问问自己,这听起来是否更像是一个任务或要求,而不是一个你已经做了大量研究和努力的问题

病房。考虑反转这个问题。不要添加单词加逗号,而是添加逗号、空格和单词,除非它是最后一个单词。此外,考虑使用String Bu建器而不是构建字符串。最后,考虑一个可以使用.String方法截断最后两个字符,并且当前字符串的长度减去适当的数量。谢谢先生的建议。就我个人而言,在现实生活中,如果单词[i]=null(i),我会这样做。首先,不要把它放在那里。建议:读你的帖子,问问自己这听起来不是更像是一个任务或需求,而不是一个你已经做了大量研究和努力的问题。不要添加单词加逗号,而是添加逗号、空格和单词,除非它是最后一个单词。此外,考虑使用String Bu建器而不是构建字符串。最后,考虑一个可以使用.String方法截断最后两个字符,并且当前字符串的长度减去适当的数量。谢谢先生的建议。就我个人而言,在现实生活中,如果words[I]==null | | words[I],我会这样做。我希望你给出解决方案,但我得到的输出与我以前的代码相同。举个例子?我得到了忍者、武士和浪人的输出,这不是你想要的吗?谢谢你的解决方案,但我得到的输出与我以前的代码相同。举个例子?我得到的输出是忍者、武士和浪人,这不是你想要的吗?如果单词以空字符串开头,结果是一个前导逗号是的,你是对的@AJNeufeld。更改了我的代码。Thanks如果单词以空字符串开头,则结果为前导逗号Yes,您是对的@AJNeufeld。更改了我的代码。谢谢