[英]How do I keep track of input words for both line and placement?
在Java中,我正在研究一个程序,该程序读取给定的文本文件并记录单词出现的次数以及出现的每个位置(格式为“ lineNumber,wordNumber ”)。
尽管我使用这些信息的方法很可靠,但是我想出一种算法,无法正确计算行数和位置(第一行中的单词除外)。
例如,如果文本是
hello there
who are you hello
单词对象将获得信息
hello appearances: 2 [1-1] [2-4]
there appearances: 1 [1-2]
who appearances: 1 [2-1]
are appearances: 1 [2-2]
you appearances: 1 [2-3]
这是我所拥有的基本版本:
lineNumber = 0;
wordNumber = 0;
while (inputFile.hasNextLine())
{
lineNumber++;
while (inputFile.hasNext())
{
wordNumber++;
word = inputFile.next();
//an algorithm to remove cases that aren't letters goes here
Word w = new Word(word);
w.setAppearance(lineNumber, wordNumber);
}
但是,当然,这种方法的问题在于hasNext()
与hasNextLine()
hasNext()
冲突,因为HasNext()
显然会自动转到文本文件中的下一行,因此lineNumber没有机会增加,因此任何单词在第1行获得错误的记录之后。
我该如何解决? 如果这足够复杂,以至于我需要再次导入,该怎么用?
您不需要2个while语句。 抓起整行,然后使用String.split函数从该行中获取单词(您可以使用空格分隔该字符)。 另外, 这可能有助于逐行阅读。
首先,无需外while
-删除。 其次,不需要Word
类-将其删除。
接下来,您需要一个可以为每个单词存储多个值的结构。 合适的结构应为Map<String, List<Map.Entry<Integer, Integer>>>
。
此代码在几行中完成了整个工作:
Map<String, List<Map.Entry<Integer, Integer>>> map = new HashMap<>();
for (int lineNumber = 1; inputFile.hasNext(); lineNumber++) {
int wordNumber = 0;
for (String word : inputFile.next().split(" "))
map.merge(word, new LinkedList<>(Arrays.asList(
new AbstractMap.SimpleEntry<>(lineNumber, ++wordNumber))),
(a, b) -> {a.addAll(b); return a;});
}
map.entrySet().stream().map(e -> String.format("%s appearances: %d %s",
e.getKey(), e.getValue().size(), e.getValue().stream()
.map(d -> String.format("[%d-%d]", d.getKey(),d.getValue())).collect(Collectors.joining(" "))))
.forEach(System.out::println);
这是一些测试代码:
Scanner inputFile = new Scanner(new ByteArrayInputStream("foo bar baz foo foo\nbar foo bar\nfoo foo".getBytes()));
Map<String, List<Map.Entry<Integer, Integer>>> map = new HashMap<>();
for (int lineNumber = 1; inputFile.hasNext(); lineNumber++) {
int wordNumber = 0;
for (String word : inputFile.next().split(" "))
map.merge(word, new LinkedList<>(Arrays.asList(
new AbstractMap.SimpleEntry<>(lineNumber, ++wordNumber))),
(a, b) -> {a.addAll(b); return a;});
}
map.entrySet().stream().map(e -> String.format("%s appearances: %d %s",
e.getKey(), e.getValue().size(), e.getValue().stream()
.map(d -> String.format("[%d-%d]", d.getKey(),d.getValue())).collect(Collectors.joining(" "))))
.forEach(System.out::println);
输出:
bar appearances: 3 [2-1] [6-1] [8-1]
foo appearances: 6 [1-1] [4-1] [5-1] [7-1] [9-1] [10-1]
baz appearances: 1 [3-1]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.