java - 使用正则表达式选择最长和最短单词时出现循环问题
问题描述
我需要选择所有最大长度的单词和所有最小长度的单词。
例如:
When I was younger, so much younger than today
I never needed anybody's help in any way
But now these days are gone, I'm not so self-assured
Now I find I've changed my mind
I've opened up the doors
输出示例:
Min: I, s, m
Max: younger, anybody, assured, changed
我已经弄清楚了算法,但它只是在排序循环之后终止(使用 int k),我不知道为什么,因为由于我的单元测试,调试器什么也没说。它只是停止。你能帮我弄清楚为什么它不起作用吗?PS我不能使用容器类
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Part2 {
public static void main(String[] args) {
String input = Util.getInput("part2.txt");
System.out.print(convert(input));
}
public static String convert(String input) {
Pattern p = Pattern.compile("[A-zА-я]+");
Matcher m = p.matcher(input);
int i = 0;
String[] arr = new String[100];
while (m.find()){
arr[i] = m.group(0);
i++;
}
StringBuilder longestResult = new StringBuilder();
longestResult.append("Max: ");
StringBuilder shortestResult = new StringBuilder();
shortestResult.append("Min: ");
int longest = 0;
int shortest = arr[0].length();
for (int k = 0; k < arr.length; k++){
if (arr[k].length() > longest){
longest = arr[k].length();
}
if (arr[k].length() < shortest){
shortest = arr[k].length();
}
}
for ( String word : arr) {
if (word.length() == longest) {
longestResult.append(word + ", ");
}
if (word.length() == shortest) {
shortestResult.append(word + ", ");
}
}
return shortestResult.substring(1, shortestResult.length() - 2) +
longestResult.substring(1, longestResult.length() - 2);
}
}
解决方案
即使没有调试器,您面临的问题也非常简单且易于调试。您的代码有一个主方法,可以由您选择的 IDE 运行以进行调试。我建议你看看如何调试你的代码,以帮助你以后解决更复杂的问题。
仅通过查看代码,我就发现了一个概念性问题。您正在创建一个在 while 循环中部分填充的字符串数组。null
除非您为它们分配值,否则所有这些元素都是。所以第一个i
元素将有一个 String 集,所有其他元素都是null
. 之后,您将遍历整个数组 ( k < arr.length
)。问题出现在这个 for 循环中,因为您尝试调用length()
-elements null
。将从第 -th 元素开始arr[k].length()
抛出NullPointerException 。i
同样的问题稍后再次发生word.length()
。运行您的代码确认上述内容:
线程“主”java.lang.NullPointerException 中的异常
与if (arr[k].length() > longest){
. 解决此问题的一种方法(在许多方法中)是仅遍历数组中实际包含值 ( ) 的元素,如下所示0 .. (i-1)
:for (int k = 0; k < (i - 1); k++){
这同样适用于第二个 for 循环。
更好的解决方案是使用String#split()
which 接受一个正则表达式,定义在哪里拆分输入并直接返回一个数组。这个数组没有空元素,只包含足够的元素来保存结果。您可以用它替换您的 while 循环,并拥有一个适用于 100 多个单词且没有硬编码限制的解决方案。如果你使用它,你不需要修改你的循环。
String[] arr = input.split("[\\p{Punct}\\s]+");
补充说明:
- 使用 a
StringJoiner
而不是 aStringBuilder
有一种干净的方式来获取逗号分隔的值:StringJoiner longestWords = new StringJoiner(", ")
然后使用longestWords.add(word)
并最终构造结果"Max: " + longestWords
。 - 您需要找到一种在结果中不包含重复值的方法。
推荐阅读
- oauth-2.0 - 跳过 keycloak 的会话 cookie
- javascript - 启动画面阻止网站交互
- python - 分配错误之前引用的python'x_min'
- android - 在android中的共享元素转换中调用多个活动
- java - 如何在android studio中格式化更大的数字
- python - pandas row中棘手字符串的建议
- javascript - 如果条件运行即使是假的,也很困惑
- r - 允许空值“”作为 selectInput 中的选项
- youtube-api - Youtube 数据 API:Python 快速入门:授权 URL 为“未经 Google 验证”
- node.js - Random file upload with multer & node.js api