微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

搜索两个日期之间所有日期的平均温度

如何解决搜索两个日期之间所有日期的平均温度

我目前正在研究如何计算一天的平均温度。一天通常有 24 次测量,00:00 01:00...等。该文件包含以“;”分隔的信息。像这样:

2020-12-30;18:00:00;1.9;G
2020-12-30;19:00:00;1.3;G
2020-12-30;20:00:00;1.1;G
2020-12-30;21:00:00;1.0;G
2020-12-30;22:00:00;1.1;G
2020-12-30;23:00:00;1.3;G
2020-12-31;00:00:00;1.1;G
2020-12-31;01:00:00;1.4;G
2020-12-31;02:00:00;1.9;G
2020-12-31;03:00:00;1.9;G
2020-12-31;04:00:00;2.4;G

我设法将数据存储在构造类型数据的列表中:这是我读取文件调用构造函数以创建具有以下信息的对象,LocalDateTime,degrees,无论测量是否被批准。

public void loadData(String filePath) throws IOException {
    List<String> fileData = Files.readAllLines(Paths.get(filePath));
    for (String fileDatum : fileData) {
        List<String> list = Arrays.asList(fileDatum.split(";"));
        LocalDateTime localDateTime = LocalDateTime.of(
                LocalDate.parse(list.get(0)),LocalTime.parse(list.get(1)));
        double temp = Double.parseDouble(list.get(2));
        String kontroll = list.get(3);
        Data data = new Data(localDateTime,kontroll,temp);
        vaderData.add(data);
    }
}

这是我试图计算一天平均温度的地方。我设法计算了一天,但我真的不明白如何在不必再次迭代整个列表的情况下继续到第二天。我也尝试过使用 Collectors 类,但都没有运气。

public List<String> averageTemperatures(LocalDate dateFrom,LocalDate dateto) {
    double sum = 0;
    int count = 0;
    for (Data average : vaderData) {
        if (dateFrom.isEqual(average.getDate().toLocalDate())) {
            sum = sum + average.getTemp();
            count++;
        }
    }
    /*
    Map<LocalDate,Double> Averagetemperature = vaderData.stream()
            .filter(Data -> !Data.getDate().toLocalDate().isAfter(dateto)
                    && !Data.getDate().toLocalDate().isBefore(dateFrom))
            .collect(Collectors.groupingBy(Data::getDate,Collectors.averagingDouble(Data::getTemp)));
    */
    return null;
}

解决方法

如果您想获得某个范围内每天的平均值,您可以使用带有分组、过滤和映射的流 API 来执行以下操作:

Map<LocalDate,Double> averages = vaderData.stream()
        .collect(Collectors.groupingBy(d -> d.localDateTime.toLocalDate()))
        .entrySet() // set of map entries with key as local date and value as list of data
        .stream() // stream of map entries
        // filter such that only dates >= from and < to are considered
        .filter(e -> (e.getKey().isEqual(from) || e.getKey().isAfter(from)) && e.getKey().isBefore(to))
        // map entries such that key is local date and value is average temp for that day
        .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(),e.getValue().stream()
                .mapToDouble(d -> d.temp)
                .average()
                .orElse(Double.NaN)))
        // collect it all as a map with key as the day and value as the average
        .collect(Collectors.toMap(
                AbstractMap.SimpleEntry::getKey,AbstractMap.SimpleEntry::getValue));

假设:

数据类定义如下

class Data {
    final LocalDateTime localDateTime;
    final String kontroll;
    final double temp;

    Data(LocalDateTime localDateTime,String kontroll,double temp) {
        this.localDateTime = localDateTime;
        this.kontroll = kontroll;
        this.temp = temp;
    }
}

上面使用的 from / to 参数类似于

LocalDate from = LocalDate.parse("2020-12-30");
LocalDate to = LocalDate.parse("2020-12-31");

它们是这样的,from 是包含的,to 是不包括的。

通过上面的输入你会得到

{2020-12-30=1.2833333333333334}

与提供的数据对应的2020-12-30的平均气温。

编辑

从评论中获取计数和其他信息,请查看 summaryStatistics() 方法。更多信息请访问:DoubleSummaryStatistics

示例

mapToDouble 位之后,而不是 average(),使用 summaryStatistics 您将获得最小值、最大值、计数、总和和平均值的信息。

此时它的返回类型不再是 Map<LocalDate,Double>,而是 Map<LocalDate,DoubleSummaryStatistics>

,

您可以从这些字符串中收集列表树形图。键 - LocalDate,值 - List<Double>。然后,您可以从指定日期之间的地图中选择 subMap,并从列表中获取 averageminmax 值,或者以某种方式 filter :

String[] info = {
        "2020-12-30;18:00:00;1.9;G","2020-12-30;19:00:00;1.3;G","2020-12-30;20:00:00;1.1;G","2020-12-30;21:00:00;1.0;G","2020-12-30;22:00:00;1.1;G","2020-12-30;23:00:00;1.3;G","2020-12-31;00:00:00;1.1;G","2020-12-31;01:00:00;1.4;G","2020-12-31;02:00:00;1.9;G","2020-12-31;03:00:00;1.9;G","2020-12-31;04:00:00;2.4;G"};
TreeMap<LocalDate,List<Double>> map = Arrays.stream(info)
        // Stream<String[]>
        .map(row -> row.split(";"))
        .collect(Collectors.toMap(
                // key - LocalDate
                arr -> LocalDate.parse(arr[0]),// value - List<Double>
                arr -> List.of(Double.parseDouble(arr[2])),// concatenate values with the same key
                (list1,list2) -> {
                    ArrayList<Double> list =
                            new ArrayList<>();
                    list.addAll(list1);
                    list.addAll(list2);
                    return list;
                },TreeMap::new));
// output a sub-map between two dates inclusive with average values
LocalDate fromDate = LocalDate.parse("2020-12-30");
LocalDate toDate = LocalDate.parse("2020-12-31");
map.subMap(fromDate,true,toDate,true)
        .forEach((key,value) -> {
            double avg = value.stream()
                    .mapToDouble(d -> d)
                    .average().orElse(0.0);
            System.out.println(key + " " + avg);
        });

输出:

2020-12-30 1.2833333333333334
2020-12-31 1.7399999999999998

另见:Convert a map of lists into a list of maps

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。