首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >获取某个单词/文本出现的行号。

获取某个单词/文本出现的行号。
EN

Stack Overflow用户
提问于 2015-04-30 13:14:59
回答 3查看 1K关注 0票数 4

我拥有的:,我有一个文件,它是逐行读取的。这些行不在文件中计算。

我想要做的事情:,我想计数一条流中的每一行,并且只返回发生特定文本的数字。

到目前为止我所拥有的:

代码语言:javascript
运行
复制
public static Integer findLineNums(String word)
        throws IOException {

    final Map<String, Integer> map = new HashMap<>();
    final List<String> lines = Files.lines(Paths.get(PATH)).collect(Collectors.toList());                 
    IntStream.rangeClosed(0, lines.size()-1).forEach(f -> map.put(lines.get(f), f+1));

    return map.get(word);
}

问:我如何只用一个流就可以做到这一点?

编辑的问题:我想做流中的每一件事,这也包括在列表中的积累。

最好的情况是:

代码语言:javascript
运行
复制
Files.lines(Paths.get(PATH)).superAwesomeStreamFuncs().collect(Collectors.toList());

编辑:在我的例子中,我只返回一个Integer,但是我想得到类似于Integer列表的内容。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-04-30 14:01:39

这样做是可行的:

代码语言:javascript
运行
复制
int[] i = new int[]{0}; // trick to make it final
List<Integer> hits = <your stream>
  .map(s -> s.contains(word) ? ++i[0] : - ++i[0])
  .filter(n -> n > 0)
  .collect(Collectors.toList());

这里的主要“技巧”是数组的使用,它的引用不会改变(即它是“有效的终结”,但它允许我们将它的(仅)元素作为计数器,它是以行方式递增的)。一个快速的过滤器扔出非火柴。

一些测试代码:

代码语言:javascript
运行
复制
String word = "foo";
int[] i = new int[]{0};
List<Integer> hits = Stream.of("foo", "bar", "foobar")
.map(s -> s.contains(word) ? ++i[0] : - ++i[0])
.filter(n -> n > 0)
.collect(Collectors.toList());
System.out.println(hits);

输出:

代码语言:javascript
运行
复制
[1, 3]
票数 3
EN

Stack Overflow用户

发布于 2015-04-30 13:30:02

下面的代码片段将创建一个包含单词的行的List<Integer>

代码语言:javascript
运行
复制
String word = "foo";
List<Integer> matchedLines = new ArrayList<>();
final List<String> lines = Files.readAllLines(Paths.get("word_list.txt"));
IntStream.rangeClosed(0, lines.size() - 1).forEach(f -> {
    if (lines.get(f).contains(word)) {
        matchedLines.add(++f);
    }
});
System.out.println("matchedLines = " + matchedLines);

假设文件word_list.txt

代码语言:javascript
运行
复制
foo
bar
baz
foobar
barfoo

输出是

代码语言:javascript
运行
复制
matchedLines = [1, 4, 5]

编辑以使用单个流解决它,创建一个自定义Consumer

代码语言:javascript
运行
复制
public class MatchingLines {

    static class MatchConsumer implements Consumer<String> {
        private int count = 0;
        private final List<Integer> matchedLines = new ArrayList<>();
        private final String word;

        MatchConsumer(String word) {
            this.word = word;
        }

        @Override
        public void accept(String line) {
            count++;
            if (line.contains(this.word)) {
                matchedLines.add(count);
            }
        }

        public List<Integer> getResult() {
            return matchedLines;
        }
    }

    public static void main(String[] args) throws IOException {
        MatchConsumer matchConsumer = new MatchConsumer("foo");
        Files.lines(Paths.get("word_list.txt")).forEach(matchConsumer);
        System.out.println("matchedLines = " + matchConsumer.getResult());
    }
}
票数 3
EN

Stack Overflow用户

发布于 2015-04-30 14:25:41

此方法返回按文件中其编号映射的行。

代码语言:javascript
运行
复制
public static Map<String, Integer> findLineNums(Path path, String word) throws IOException {

        final Map<String, Integer> map = new HashMap<>();
        int lineNumber = 0;
        Pattern pattern = Pattern.compile("\\b" + word + "\\b");

        try (BufferedReader reader = Files.newBufferedReader(path)) {
            String line = null;
            while ((line = reader.readLine()) != null) {
                lineNumber++;
                if (pattern.matcher(line).find()) {
                    map.put(line, lineNumber);
                }
            }
        }
        for (String line : map.keySet()) {
            Integer lineIndex = map.get(line);
            System.out.printf("%d  %s\n", lineIndex, line);
        }
        return map;
    }

BufferedReader逐行读取文件,Files.lines流也是如此。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29968763

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档