处理环法自行车赛Dauphiné站的结果

作者: Paul King
发布: 2023-06-13 05:00PM


2023 年 环法自行车赛Dauphiné站 刚刚结束。让我们使用 Groovy 和 DuckDB 来检查结果。出于本文的目的,我们对总成绩前十名的车手感兴趣。

结果文件

我们的结果存储在一个 CSV 文件中

lines from CSV file

之前的一篇文章 中,我们研究了使用多个 CSV 库读取和写入 CSV 文件。今天我们将使用 DuckDB 的一个很好的功能,它可以即时读取 CSV 文件。

我们的目标非常简单,只是打印出信息,但按每个车手的国家分组。

Sql.withInstance('jdbc:duckdb:', 'org.duckdb.DuckDBDriver') { sql ->
    println "Country  Riders                                  Places    Count"
    sql.eachRow("""SELECT Country,
        rpad(string_agg(Rider, ', '), 40, ' ') as Riders,
        rpad(string_agg(Place, ', '), 10, ' ') as Places,
        bar(count(Country), 0, 4, 30) as Count
        FROM 'topten.csv' GROUP BY Country""") { row ->
        row.with {
            println "$Country       $Riders$Places$Count"
        }
    }
}

在这里,我们使用 DuckDB 中的几个内置函数,包括 rpad 来右填充输出、string_agg 来聚合来自同一国家的车手(及其排名),以及 bar 来生成一个漂亮的条形图。

运行此代码会产生以下输出

Country  Riders                                  Places    Count
🇩🇰       JONAS VINGEGAARD                        1         ███████▌
🇬🇧       ADAM YATES                              2         ███████▌
🇦🇺       BEN O’CONNOR, JAI HINDLEY, JACK HAIG    3, 4, 5   ██████████████████████▌
🇫🇷       GUILLAUME MARTIN, JULIAN ALAPHILIPPE    6, 10     ███████████████
🇿🇦       LOUIS DU BOUISSON MEINTJES              7         ███████▌
🇳🇴       TORSTEIN TRÆEN                          8         ███████▌
🇪🇸       CARLOS RODRIGUEZ CANO                   9         ███████▌

我们可以使用 GQuery(又名 GINQ)使用以下代码获得类似的结果

var f = 'topten.csv' as File
var lines = f.readLines()*.split(',')
var cols = lines[0].size()
var rows = lines[1..-1].collect{row ->
    (0..<cols).collectEntries{ col -> [lines[0][col], row[col]] }}
var commaDelimited = Collectors.joining(', ')
var aggRiders = { it.stream().map(rec -> rec.r.Rider).collect(commaDelimited) }
var aggPlaces = { it.stream().map(rec -> rec.r.Place).collect(commaDelimited) }
println GQ {
    from r in rows
    groupby r.Country
    select r.Country,
        agg(aggRiders(_g)) as Riders,
        agg(aggPlaces(_g)) as Places,
        '██' * count(r.Country) as Count
}

我们可以使用 CSV 库来读取数据,但对于这个简单的例子,我们只会使用 Groovy 的行/文本处理功能。GQuery 目前还没有内置的 barstring_agg 等价物,因此我们自己编写了粗糙的条形字符函数和聚合器,aggRidersaggPlaces

运行此代码会产生以下输出

+---------+--------------------------------------+---------+--------+
| Country | Riders                               | Places  | Count  |
+---------+--------------------------------------+---------+--------+
| 🇦🇺      | BEN O’CONNOR, JAI HINDLEY, JACK HAIG | 3, 4, 5 | ██████ |
| 🇩🇰      | JONAS VINGEGAARD                     | 1       | ██     |
| 🇳🇴      | TORSTEIN TRÆEN                       | 8       | ██     |
| 🇿🇦      | LOUIS DU BOUISSON MEINTJES           | 7       | ██     |
| 🇬🇧      | ADAM YATES                           | 2       | ██     |
| 🇪🇸      | CARLOS RODRIGUEZ CANO                | 9       | ██     |
| 🇫🇷      | GUILLAUME MARTIN, JULIAN ALAPHILIPPE | 6, 10   | ████   |
+---------+--------------------------------------+---------+--------+

对于 Groovy 5,我们目前正在探索在 GQuery 中添加更多函数的可能性,例如 barstringAgg。如果您对这些功能感兴趣,请通过 邮件列表Slack 联系我们。