接受字符串输入,将每个单词解析为全部小写,并将每个单词打印在一行上,非字母字符被视为单词之间的中断

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

提问人:J. Doe 提问时间:2/27/2019 最后编辑:J. Doe 更新时间:2/28/2019 访问量:412

问:

我正在尝试获取字符串输入,将每个单词解析为全部小写,并在一行上打印每个单词(按排序顺序),忽略非字母字符(单个字母单词也算在内)。所以

输入示例:

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 方法,以便将中断视为非字母字符而不是空格,所以这就是我现在卡住的地方。

Java 字符串 算法 解析 java.util.scanner

评论

0赞 shmosel 2/27/2019
如何翻译为 ?a t\|his@a case his
0赞 J. Doe 2/27/2019
“case”来自输入中的“case”部分。A、T 和 His 被视为单独的单词,因为它们由非字母字符分隔。
0赞 GBlodgett 2/27/2019
如何比较 Java 中的字符串?

答:

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

步骤如下:

  1. 将字符串拆分为一个或多个不按字母顺序排列的后续字符;

    input.split("[^A-Za-Z]+")
    

    这将生成仅由字母字符组成的标记

  2. 使用以下方法对生成的数组进行流式传输Arrays.stream();

  3. 将每个元素映射到其小写等效项:

    .map(t -> t.toLowerCase())
    

    使用默认区域设置。用于显式设置区域设置。toLowerCase(Locale)

  4. 使用 放弃重复项。Stream.distinct()

  5. 通过简单地调用对流中的元素进行排序sorted();

  6. 将元素收集到 with 中。Listcollect()


如果您需要从文件中读取它,您可以使用以下命令:

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 只是一个 .inputString
0赞 J. Doe 2/27/2019
那么“输入”是整个文本输入吗?
0赞 MC Emperor 2/27/2019
@J.Doe 是的,作为字符串。我将调整我的答案以包括扫描仪。
0赞 J. Doe 2/28/2019
因此,“部分”列表已正确启动,但是在执行 .stream().map 等操作时,该列表完全不受影响。