gpt4 book ai didi

java - 将 Files.lines 与 .map(line -> line.split ("multiple delimiters")) 一起使用

转载 作者:行者123 更新时间:2023-12-01 22:21:20 29 4
gpt4 key购买 nike

我有一个具有以下格式的输入文件:安大略省:布兰普顿:北纬 43° 41':西经 79° 45'安大略省:多伦多:北纬 43° 39':西经 79° 23'魁北克省:蒙特利尔:北纬 45° 30':西经 73° 31'...

我有一个名为“值将去向”的类。示例:
省份: 安大略省城市: 布兰普顿纬度:43最晚时间:41纬度方向:N长度数:79 ....等

我已经完成了一种可以正确解析此内容的方法,但我正在尝试了解是否可以使用 Streams、Lambdas 使用 Java 8 更好地完成此操作。

如果我从以下内容开始:

Files.lines(Paths.get(inputFile))

.map(line -> line.split("\\b+")) //this delimits everything
//.filter(x -> x.startsWith(":"))
.flatMap(Arrays::stream)
.forEach(System.out::println);
有人可以帮我重现以下内容吗?

private void parseLine(String data) {
int counter1 = 1; //1-2 province or city
int counter2 = 1; //1-2 LatitudeDirection,LongitudeDirection
int counter3 = 1; //1-4 LatitudeDegrees,LatitudeMinutes,LongitudeDegrees,LongitudeMinutes

City city = new City(); //create City object
//String read = Arrays.toString(data); //convert array element to String
String[] splited = data.split(":"); //set delimiter

for (String part : splited) {
//System.out.println(part);
char firstChar = part.charAt(0);
if(Character.isDigit(firstChar)){ //if the first char is a digit, then this part needs to be split again
String[] splited2 = part.split(" "); //split second time with space delimiter
for (String part2: splited2){
firstChar = part2.charAt(0);
if (Character.isDigit(firstChar)){ //if the first char is a digit, then needs trimming
String parseDigits = part2.substring(0, part2.length()-1); //trim trailing degrees or radians character
switch(counter2++){
case 1:
city.setLatitudeDegrees(Integer.parseInt(parseDigits));
//System.out.println("LatitudeDegrees: " + city.getLatitudeDegrees());
break;
case 2:
city.setLatitudeMinutes(Integer.parseInt(parseDigits));
//System.out.println("LatitudeMinutes: " + city.getLatitudeMinutes());
break;
case 3:
city.setLongitudeDegrees(Integer.parseInt(parseDigits));
//System.out.println("LongitudeDegrees: " + city.getLongitudeDegrees());
break;
case 4:
city.setLongitudeMinutes(Integer.parseInt(parseDigits));
//System.out.println("LongitudeMinutes: " + city.getLongitudeMinutes());
counter2 = 1; //reset counter2
break;
}
}else{
if(counter3 == 1){
city.setLatitudeDirection(part2.charAt(0));
//System.out.println("LatitudeDirection: " + city.getLatitudeDirection());
counter3++; //increment counter3 to use longitude next
}else{
city.setLongitudeDirection(part2.charAt(0));
//System.out.println("LongitudeDirection: " + city.getLongitudeDirection());
counter3 = 1; //reset counter 3
//System.out.println("Number of cities: " + cities.size());
cities.add(city);
}
}
}
}else{
if(counter1 == 1){
city.setProvince(part);
//System.out.println("\nProvince: " + city.getProvince());
counter1++;
}else if(counter1 == 2){
city.setCity(part);
//System.out.println("City: " + city.getCity());
counter1 = 1; //reset counter1
}
}
}
}

毫无疑问,我的 parseLine() 方法可能有更好的解决方案,但我真的很想将其浓缩为如上所述。谢谢!!

最佳答案

让我们从一些一般性注释开始。

不推荐使用您的序列.map(line -> line.split("\\b+")).flatMap(Arrays::stream)。这两个步骤将首先创建一个数组,然后再创建包装该数组的另一个流。您可以使用 splitAsStream 跳过数组步骤尽管这需要您显式处理 Pattern 而不是将其隐藏在 String.split 中:

.flatMap(Pattern.compile("\\b+")::splitAsStream)

但请注意,在这种情况下,拆分成单词并没有真正带来返回。

如果你想保留原来的parseLine方法,你可以简单地这样做

Files.lines(Paths.get(inputFile))
.forEach(this::parseLine);

你就完成了。

<小时/>

但说真的,这不是一个真正的解决方案。要进行模式匹配,您应该使用指定用于模式匹配的库,例如the regex package 。当您通过 split("\\b+") 进行拆分时,您已经在使用它了,但这远远落后于它能为您做的事情。

让我们定义模式:

  • (…) 形成一个组,允许捕获匹配部分,以便我们可以提取它作为结果
  • [^:]* 指定由除冒号 ([^:]) 之外的任意长度 (*) 之外的任意字符组成的标记)
  • \d+ 定义一个数字(d = 数字,+ = 一个或多个)
  • [NS][WE] 匹配 NS 中的单个字符,或者分别为 WE

所以您正在寻找的整个模式是

([^:]*):([^:]*):(\d+)° (\d+)' ([NS]):(\d+)° (\d+)' ([我们])

整个解析例程将是:

static Pattern CITY_PATTERN=Pattern.compile(
"([^:]*):([^:]*):(\\d+)° (\\d+)' ([NS]):(\\d+)° (\\d+)' ([WE])");

static City parseCity(String line) {
Matcher matcher = CITY_PATTERN.matcher(line);
if(!matcher.matches())
throw new IllegalArgumentException(line+" doesn't match "+CITY_PATTERN);
City city=new City();
city.setProvince(matcher.group(1));
city.setCity(matcher.group(2));
city.setLatitudeDegrees(Integer.parseInt(matcher.group(3)));
city.setLatitudeMinutes(Integer.parseInt(matcher.group(4)));
city.setLatitudeDirection(line.charAt(matcher.start(5)));
city.setLongitudeDegrees(Integer.parseInt(matcher.group(6)));
city.setLongitudeMinutes(Integer.parseInt(matcher.group(7)));
city.setLongitudeDirection(line.charAt(matcher.start(8)));
return city;
}

我真的希望你称你的难以阅读的方法不再“压缩”......

使用上面的例程,一个干净的基于流的处理解决方案看起来像

List<City> cities = Files.lines(Paths.get(inputFile))
.map(ContainingClass::parseCity).collect(Collectors.toList());

将文件收集到新的城市列表中。

关于java - 将 Files.lines 与 .map(line -> line.split ("multiple delimiters")) 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29724714/

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