gpt4 book ai didi

java - Spliterator 跳过部分文本

转载 作者:行者123 更新时间:2023-11-30 01:47:38 26 4
gpt4 key购买 nike

我遇到了流的 dropWhiletakeWhile 方法的问题,因为 spliterator 正在跳过特定模式奇数或偶数中的文本部分。应该怎样处理文本的所有部分?我的方法在这里:

void read(Path filePath) {
try {
Stream<String> lines = Files.lines(filePath);
while (true) {
Spliterator<String> spliterator = lines.dropWhile(line -> !line.startsWith("FAYSAL:")).spliterator();
Stream<String> portion = fetchNextPortion(spliterator);
if(spliterator.estimateSize() == 0)
break;
portion .forEach(System.out::println);
lines = StreamSupport.stream(spliterator, false);
}
lines.close();
}
catch (IOException e) {
e.printStackTrace();
}
}

private Stream<String> fetchNextPortion(Spliterator<String> spliterator) {
return StreamSupport.stream(spliterator, false)
.filter(this::isValidReportName)
.peek(System.out::println)
.findFirst()
.map( first -> Stream.concat(Stream.of(first),
StreamSupport.stream(spliterator, false).takeWhile(line -> !line.startsWith("FAYSAL:")))).orElse(Stream.empty());
}

示例输入是:

FAYSAL: 1
Some text here
Some text here
FAYSAL: 2
Some text here
Some text here
FAYSAL: 3
Some text here
Some text here
FAYSAL: 4
Some text here
Some text here

它将跳过 FAYSAL: 2 和 FAYSAL: 4

最佳答案

What should be done to process all portions of text?

您可以选择不同的方法。

您的代码在我的机器上产生了 StackOverflowError (还调用了 fetchNextChunk 但调用了 fetchNextPartition 方法,所以我也不确定)显示您的问题,因此我没有尝试调试它,而是想出了一种不同的分割输入的方法。鉴于我的方法在内存中包含整个字符串,它可能不适合较大的文件。稍后我可能会制定一个带有 Streams 的版本。

基本假设:您希望将输入文本分成多个部分,每个部分都以“FAYSAL:”开头的字符串开头。

这个想法与您的方法类似,但不是基于 Spliterators 并且它也不使用 dropWhile 。相反,它找到以“FAYSAL:”开头的第一个字符串(我假设这就是 isValidReportName 所做的;该方法的代码不在问题中)并将所有内容带到下一部分开始。将找到的第一个元素添加为列表的第一个元素,然后将集合添加到稍后可以使用的列表中。然后,收集的行数将从原始列表中删除。

完整代码:

import java.util.*;
import java.util.stream.Collectors;

class Main {

public static void main(String[] args) {
Main m = new Main();
System.out.println(m.partitionTextByStringStart(m.getString()));
}

private List<List<String>> partitionTextByStringStart(String text) {
List<List<String>> partitions = new ArrayList<>();
List<String> lines = Arrays.asList(text.split("\n"));

while (!lines.isEmpty()) {
String first = lines.stream().filter(this::isValidReportName).findFirst().orElse("This is prolly bad");
List<String> part = lines.stream().skip(1).takeWhile(l -> !l.startsWith("FAYSAL:")).collect(Collectors.toList());
part.add(0, first);

partitions.add(part);
lines = lines.subList(part.size(), lines.size());
}

return partitions;
}

private boolean isValidReportName(String x) {
return x.startsWith("FAYSAL:");
}

private String getString() {
return "FAYSAL: 1\n" +
"Some text here1\n" +
"Some text here1\n" +
"FAYSAL: 2\n" +
"Some text here2\n" +
"Some text here2\n" +
"FAYSAL: 3\n" +
"Some text here3\n" +
"Some text here3\n" +
"FAYSAL: 4\n" +
"Some text here4\n" +
"Some text here4";
}

}

(注意:我在这里使用静态字符串而不是文件读取来制作完整的代码示例;您可以相应地调整您的代码)

编辑:经过一些研究,我发现使用名为 StreamEx ( Github ) ( Maven ) 的库将流中的内容分组出奇地容易。在 this回答 我发现了一条关于 StreamEx#groupRuns 的注释函数正是这样做的:

private Stream<Stream<String>> partitionStreamByStringStart(Stream<String> lineStream) {
return StreamEx.of(lineStream).groupRuns((l1, l2) -> !l2.startsWith("FAYSAL:")).map(Collection::stream);
}

要查看它的工作原理,您可以添加

System.out.println(m.partitionStreamByStringStart(m.getStream()).map(
s -> s.collect(Collectors.toList())
).collect(Collectors.toList()));

到主函数

private Stream<String> getStream() {
return Stream.of(getString().split("\n"));
}

上述完整代码示例的 Main 类中的某个位置。

关于java - Spliterator 跳过部分文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57365560/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com