提问人:J. Doe 提问时间:2/27/2019 最后编辑:J. Doe 更新时间:2/28/2019 访问量:412
接受字符串输入,将每个单词解析为全部小写,并将每个单词打印在一行上,非字母字符被视为单词之间的中断
Take string input, parse each word to all lowercase and print each word on a line, non-alphabetic characters are treated as a break between words
问:
我正在尝试获取字符串输入,将每个单词解析为全部小写,并在一行上打印每个单词(按排序顺序),忽略非字母字符(单个字母单词也算在内)。所以
输入示例:
Adventures in Disneyland
Two blondes were going to Disneyland when they came to a fork in the
road. The sign read: "Disneyland Left."
So they went home.
输出:
a
adventures
blondes
came
disneyland
fork
going
home
in
left
read
road
sign
so
the
they
to
two
went
were
when
我的程序:
Scanner reader = new Scanner(file);
ArrayList<String> words = new ArrayList<String>();
while (reader.hasNext()) {
String word = reader.next();
if (word != "") {
word = word.toLowerCase();
word = word.replaceAll("[^A-Za-z ]", "");
if (!words.contains(word)) {
words.add(word);
}
}
}
Collections.sort(words);
for (int i = 0; i < words.size(); i++) {
System.out.println(words.get(i));
}
这适用于上面的输入,但会为如下所示的输入打印错误的输出:
a t\|his@ is$ a)( -- test's-&*%$#-`case!@|?
预期输出应为
a
case
his
is
s
t
test
我得到的输出是
*a blank line is printed first*
a
is
testscase
this
因此,我的程序显然不起作用,因为 scanner.next() 在遇到空格并将其视为字符串之前会接受字符,而任何不是字母的内容都应被视为单词之间的中断。我不确定我如何能够操纵 Scanner 方法,以便将中断视为非字母字符而不是空格,所以这就是我现在卡住的地方。
答:
0赞
Elliott Frisch
2/27/2019
#1
不要使用 or 进行比较。此外,在检查空之前执行转换。这==
!=
String
if (word != "") {
word = word.toLowerCase();
word = word.replaceAll("[^A-Za-z ]", "");
if (!words.contains(word)) {
words.add(word);
}
}
应该看起来像这样
word = word.toLowerCase().replaceAll("[^a-z ]", "").trim();
if (!word.isEmpty() && !words.contains(word)) {
words.add(word);
}
2赞
MC Emperor
2/27/2019
#2
另一个答案已经提到了你的代码的一些问题。
我建议另一种方法来满足您的要求。这种转换是 Java Streams 的一个很好的用例——它通常会产生干净的代码:
List<String> strs = Arrays.stream(input.split("[^A-Za-Z]+"))
.map(t -> t.toLowerCase())
.distinct()
.sorted()
.collect(Collectors.toList());
步骤如下:
将字符串拆分为一个或多个不按字母顺序排列的后续字符;
input.split("[^A-Za-Z]+")
这将生成仅由字母字符组成的标记。
使用以下方法对生成的数组进行流式传输
Arrays.stream()
;将每个元素映射到其小写等效项:
.map(t -> t.toLowerCase())
使用默认区域设置。用于显式设置区域设置。
toLowerCase(Locale)
使用 放弃重复项。
Stream.distinct()
通过简单地调用对流中的元素进行排序
sorted()
;将元素收集到 with 中。
List
collect()
如果您需要从文件中读取它,您可以使用以下命令:
Files.lines(filepath)
.flatMap(line -> Arrays.stream(line.split("[^A-Za-Z]+")))
.map(... // Et cetera
但是,如果您需要使用 ,那么您可以使用如下内容:Scanner
Scanner s = new Scanner(input)
.useDelimiter("[^A-Za-z]+");
List<String> parts = new ArrayList<>();
while (s.hasNext()) {
parts.add(s.next());
}
然后
List<String> strs = parts.stream()
.map(... // Et cetera
评论
0赞
J. Doe
2/27/2019
什么是“输入”?从技术上讲,我应该从标准输入 (System.in) 中读取输入,我现在只是从代码中的文本文件中读取它以进行调试。所以我不确定这将如何影响您的解决方案。
0赞
MC Emperor
2/27/2019
@J.Doe 只是一个 .input
String
0赞
J. Doe
2/27/2019
那么“输入”是整个文本输入吗?
0赞
MC Emperor
2/27/2019
@J.Doe 是的,作为字符串。我将调整我的答案以包括扫描仪。
0赞
J. Doe
2/28/2019
因此,“部分”列表已正确启动,但是在执行 .stream().map 等操作时,该列表完全不受影响。
评论
a t\|his@
a case his