首页 > 解决方案 > 搜索两个日期之间所有日期的平均温度

问题描述

我目前正在尝试弄清楚如何计算一天的平均温度。一天通常有 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,度数,测量是否被批准。

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;
}

标签: javaalgorithmdata-structures

解决方案


如果您想在某个范围内获取每天的平均值,您可以使用带有分组、过滤和映射的流 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>不再是 a ,而是 a Map<LocalDate, DoubleSummaryStatistics>


推荐阅读