将单词格式化为句子

时间:2018-04-27 03:18:36

标签: java

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

示例:

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

代码

public static String formatWords(String[] words)
    {
        if (words == null || words.length == 0)
        {
            return "";
        }

        String str = "";

        for (int i = 0; i < words.length; i++)
        {
            if (words[i].equals(""))
                continue;
           if (i == words.length - 1)
               str += "and " + words[i];
           else
               str += words[i] + ", ";

        }

        return str;
    }

如何删除最后一个逗号?

5 个答案:

答案 0 :(得分:3)

一个简单的解决方案是按降序运行循环。我对您的代码进行了一些更改..希望,这有效

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;
}

编辑:修改了添加Vector以解决@AJNeufeld在评论中提到的问题

答案 1 :(得分:2)

您可以使用String.join使用逗号创建String。然后用正则表达式替换最后一个逗号。

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"}));
  

忍者
  忍者和武士郎   忍者,武士和浪人

注意:

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

Stream.of(values)
      .filter(s -> s != null && !s.isEmpty())
      .collect(joining(", "))

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

答案 2 :(得分:0)

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

最佳做法是在重复附加StringBuilder时使用String,以避免重复(浪费)内存分配。

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();
}

答案 3 :(得分:0)

如果您使用的是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;
}

首先在代码中构造一个结果String(res),所有分隔符都是逗号。

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

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

和其他应该直到字符串的结尾:

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

最后将这两个子串合并为" and "

答案 4 :(得分:0)

我觉得这是一项家庭作业,所以我不打算给你完整的解决方案,但是我会指出你正确的轨道,而不使用像ArrayList<String>,{{{{{}}这样的高级概念。 1}},Vector<String>和正则表达式,可能还没有被教过。

此作业中的最大挑战是正确跳过Stream.of(...)数组中的null / nil值,并仍然找到逗号分隔符和最终words分隔符的正确位置。循环遍历" and "数组时,words条目不一定标记第一个真实单词,因为数组可能以i == 0或空null开头。同样,String条目不一定代表最后一个单词,因为数组可能以i == words.length-1或空null结尾。这意味着循环索引String实际上无用于确定是否需要分隔符以及使用哪个分隔符。

由于循环索引或多或少没用,我们可以使用“enhanced for-loop”构造来循环遍历数组中的单词:

i

如果您还没有学习“增强型for循环”,您可以坚持:

for(String word : words) {
    // ... code here
}

但请理解,您不会在循环内的任何其他位置使用值for(int i = 0; i < words.length; i++) { String word = words[i]; // ... code here } 。因此,我将继续在讨论的其余部分使用“增强的for循环”,但是知道这是一个简单的替换,将其更改为常规的for循环。

您需要知道的第一件事是“i数组中有多少个单词?”答案不是words,因为words.length值和空null值的可能性。最简单的方法是使用循环计算有效单词:

String

通过知道有int numWords = 0; for(String word : words) { if (word != null && !word.isEmpty()) { numWords++; } } 个单词,您现在可以果断地说numWord分隔符位于最后一个单词之前,这个单词将从" and "开始(从1开始计算)字。

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

wordNumber

我遗漏了添加单词和相应分隔符的最后一步的实际代码。这与OP解决问题的初始尝试没有太大的不同,因此应该明白如何继续,但不是Stack-Overflow的复制和粘贴作业解决方案。学生至少做了一些工作。

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

显然,在这个例子中并非如此。数据在一个数组中;您可以根据需要多次循环数据。但是仍然可以只使用一个循环来进行操作。

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

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.
    }
}

同样,我遗漏了确定是否需要分隔符的关键代码,并将其和最新的单词添加到结果中。再次,请留给学生,以避免从Stack-Overflow家庭作业解决方案中复制和粘贴。

如其他地方所述,使用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可以提高上述两种解决方案的代码效率。这不是必需的,但是如果你被教会如何使用它,你应该使用它!