You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by gi...@apache.org on 2026/08/26 00:45:05 UTC

(groovy-dev-site) branch asf-site updated: 2026/08/26 00:45:00: Generated dev website from groovy-website@440fb39

This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/groovy-dev-site.git


The following commit(s) were added to refs/heads/asf-site by this push:
     new e0ee0ba1 2026/08/26 00:45:00: Generated dev website from groovy-website@440fb39
e0ee0ba1 is described below

commit e0ee0ba1eeb29c6f33dd35ac8d5d455791b4f53e
Author: jenkins <bu...@apache.org>
AuthorDate: Wed Aug 26 00:45:00 2026 +0000

    2026/08/26 00:45:00: Generated dev website from groovy-website@440fb39
---
 blog/feed.atom                          |   4 +-
 blog/img/csv_summary.png                | Bin 0 -> 230321 bytes
 blog/img/csv_typed.png                  | Bin 0 -> 184483 bytes
 blog/index.html                         |   2 +-
 blog/reading-and-writing-csv-files.html |  94 ++++++++++++++++++++++++++++++--
 search/search-index.json                |   4 +-
 6 files changed, 94 insertions(+), 10 deletions(-)

diff --git a/blog/feed.atom b/blog/feed.atom
index b24a660a..aaf39ced 100644
--- a/blog/feed.atom
+++ b/blog/feed.atom
@@ -4,7 +4,7 @@
   <link href="http://groovy.apache.org/blog"/>
   <link href="http://groovy.apache.org/blog/feed.atom" rel="self"/>
   <id>http://groovy.apache.org/blog</id>
-  <updated>2026-08-25T10:00:00Z</updated>
+  <updated>2026-08-26T10:00:00Z</updated>
   <entry>
     <id>http://groovy.apache.org/blog/groovy-geaflow</id>
     <author>
@@ -782,7 +782,7 @@
     </author>
     <title type="html">Reading and Writing CSV files with Groovy&amp;trade;</title>
     <link href="http://groovy.apache.org/blog/reading-and-writing-csv-files"/>
-    <updated>2026-08-25T10:00:00Z</updated>
+    <updated>2026-08-26T10:00:00Z</updated>
     <published>2022-07-25T14:26:20Z</published>
     <summary type="html">This post looks at processing CSV files using Groovy's groovy-csv module, along with the OpenCSV, Apache Commons CSV, and Jackson Databind libraries.</summary>
   </entry>
diff --git a/blog/img/csv_summary.png b/blog/img/csv_summary.png
new file mode 100644
index 00000000..d21a981b
Binary files /dev/null and b/blog/img/csv_summary.png differ
diff --git a/blog/img/csv_typed.png b/blog/img/csv_typed.png
new file mode 100644
index 00000000..51fce58c
Binary files /dev/null and b/blog/img/csv_typed.png differ
diff --git a/blog/index.html b/blog/index.html
index dbdf3dc2..ad4f4fb4 100644
--- a/blog/index.html
+++ b/blog/index.html
@@ -63,7 +63,7 @@
                                     </ul>
                                 </div>
                             </div>
-                        </div><div id='content' class='page-1'><div class='row'><div class='row-fluid'><div class='col-lg-3' id='blog-index'><ul class='nav-sidebar list'><li class='active'><a href='/blog/'>Blogs</a></li><li><a href='reading-and-writing-csv-files'>Reading and Writing CSV files with Groovy&trade;</a></li><li><a href='groovy6-formal-methods'>Groovy 6 features for formal method advocates</a></li><li><a href='groovy-null-checker'>Compile-time null safety for Groovy&trade;</a> [...]
+                        </div><div id='content' class='page-1'><div class='row'><div class='row-fluid'><div class='col-lg-3' id='blog-index'><ul class='nav-sidebar list'><li class='active'><a href='/blog/'>Blogs</a></li><li><a href='reading-and-writing-csv-files'>Reading and Writing CSV files with Groovy&trade;</a></li><li><a href='groovy6-formal-methods'>Groovy 6 features for formal method advocates</a></li><li><a href='groovy-null-checker'>Compile-time null safety for Groovy&trade;</a> [...]
                             <div class='row'>
                                 <div class='colset-3-footer'>
                                     <div class='col-1'>
diff --git a/blog/reading-and-writing-csv-files.html b/blog/reading-and-writing-csv-files.html
index 890ef419..e7df02e0 100644
--- a/blog/reading-and-writing-csv-files.html
+++ b/blog/reading-and-writing-csv-files.html
@@ -63,7 +63,14 @@
                                     </ul>
                                 </div>
                             </div>
-                        </div><div id='content' class='page-1'><div class='row'><div class='row-fluid'><div class='col-lg-3'><ul class='nav-sidebar'><li><a href='./'>Blog index</a></li><li class='active'><a href='#doc'>Reading and Writing CSV files with Groovy&trade;</a></li><li><a href='#_introduction' class='anchor-link'>Introduction</a></li><li><a href='#_groovys_csv_module' class='anchor-link'>Groovy&#8217;s CSV module</a></li><li><a href='#_commons_csv' class='anchor-link'>Commons C [...]
+                        </div><div id='content' class='page-1'><div class='row'><div class='row-fluid'><div class='col-lg-3'><ul class='nav-sidebar'><li><a href='./'>Blog index</a></li><li class='active'><a href='#doc'>Reading and Writing CSV files with Groovy&trade;</a></li><li><a href='#_introduction' class='anchor-link'>Introduction</a></li><li><a href='#_groovys_csv_module' class='anchor-link'>Groovy&#8217;s CSV module</a></li><li><a href='#_commons_csv' class='anchor-link'>Commons C [...]
+<div class="sectionbody">
+<div class="paragraph">
+<p><span class="image"><img src="./img/csv_typed.png" alt="Reading a CSV file by hand with split versus reading it into records with Groovy&#8217;s CsvSlurper" width="800"></span></p>
+</div>
+</div>
+</div>
+<div class="sect1">
 <h2 id="_introduction">Introduction</h2>
 <div class="sectionbody">
 <div class="paragraph">
@@ -370,10 +377,78 @@ assert sales[0].date.monthValue == 3</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>Writing typed objects back out is <code>CsvBuilder.toCsv(data, type)</code>. One
-thing to watch there: the column order comes from Jackson&#8217;s view of the
-type rather than the declaration order, so if the exact ordering
-matters, supply a schema yourself.</p>
+<p>Writing typed objects back out is <code>CsvBuilder.toCsv(data, type)</code>.
+Records are written in component declaration order and other classes
+alphabetically. If the order matters, <code>@JsonPropertyOrder</code> on the type
+pins it explicitly; records came out alphabetically too in Groovy 6 beta versions,
+and the annotation gives the same result either way.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_revisiting_the_summary">Revisiting the summary</h3>
+<div class="paragraph">
+<p>Now that our rows are records, we can revisit the multiple wins summary
+from earlier. The grouping key becomes the interesting part of the line
+rather than a column index, and <code>countBy</code> does in one step what
+<code>groupBy</code> followed by a size mapping did before, so the <code>bySize</code> helper
+has no equivalent here:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="groovy">def multipleWins = { Closure select -&gt; cyclists
+    .countBy(select)
+    .findAll { it.value &gt; 1 }
+    .sort { -it.value }
+    .entrySet()
+    .join(', ')
+}
+println 'Multiple wins by country:\n' + multipleWins{ it.country }
+println 'Multiple wins by rider:\n' + multipleWins{ it.full() }
+println 'Multiple wins by team:\n' + multipleWins{ it.team }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The output is identical to the earlier version, but nothing in the
+processing depends any more on which position a column happens to
+occupy in the file.</p>
+</div>
+<div class="paragraph">
+<p><span class="image"><img src="./img/csv_summary.png" alt="The multiple wins summary rewritten with records and countBy, alongside its output" width="800"></span></p>
+</div>
+<div class="paragraph">
+<p>Groovy&#8217;s <code>groovy-ginq</code> module is worth a mention here too. GINQ can
+group by several keys at once, so the team and country travel along
+with the rider, and a second aggregate comes with them in the same
+pass:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="groovy">def repeatWinners = GQ {
+    from c in cyclists
+    groupby c.full() as rider, c.team as team, c.country as country
+    having count() &gt; 1
+    orderby count() in desc, rider
+    select rider, team, country, count() as wins, max(c.stage) as lastWin
+}
+repeatWinners.each {
+    println "$it.wins wins  $it.rider ($it.team, $it.country), last on stage $it.lastWin"
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>which gives us:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code>3 wins  Tadej Pogaฤar (UAE Team Emirates, ๐Ÿ‡ธ๐Ÿ‡ฎ), last on stage 17
+3 wins  Wout van Aert (Jumbo-Visma, ๐Ÿ‡ง๐Ÿ‡ช), last on stage 20
+2 wins  Jasper Philipsen (Alpecin-Deceuninck, ๐Ÿ‡ง๐Ÿ‡ช), last on stage 21
+2 wins  Jonas Vingegaard (Jumbo-Visma, ๐Ÿ‡ฉ๐Ÿ‡ฐ), last on stage 18</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Doing that with closures means holding on to a representative element
+for each group and re-extracting the other columns from it.</p>
 </div>
 <div class="paragraph">
 <p>The module is incubating in Groovy 6, so we&#8217;d love your feedback. The
@@ -680,6 +755,15 @@ OpenCSV, Commons CSV and Jackson Databind CSV libraries.</p>
 <p>Code for other examples of using Groovy for Data Science:<br>
 <a href="https://github.com/paulk-asert/groovy-data-science" class="bare">https://github.com/paulk-asert/groovy-data-science</a></p>
 </div>
+<div class="sidebarblock">
+<div class="content">
+<div class="title">Update history</div>
+<div class="paragraph">
+<p><strong>25/Jul/2022</strong>: Initial version.<br>
+<strong>26/Aug/2026</strong>: Version 2: added a section on Groovy 6&#8217;s <code>groovy-csv</code> module โ€” <code>CsvSlurper</code>, <code>CsvBuilder</code>, RFC 4180 quoting, and typed <code>parseAs</code> reading straight into records; revisited the multiple wins summary using records with <code>countBy</code>, and with a <code>groovy-ginq</code> query grouping by several keys at once.</p>
+</div>
+</div>
+</div>
 </div>
 </div></div></div></div></div><footer id='footer'>
                             <div class='row'>
diff --git a/search/search-index.json b/search/search-index.json
index 5097a7ee..e9d48f80 100644
--- a/search/search-index.json
+++ b/search/search-index.json
@@ -366,7 +366,7 @@
     {
         "id": "blog/reading-and-writing-csv-files.html",
         "title": "The Apache Groovy programming language - Blogs - Reading and Writing CSV files with Groovy&trade;",
-        "content": "The Apache Groovy programming language - Blogs - Reading and Writing CSV files with Groovy&trade; Socialize Discuss on the mailing list Groovy on X Groovy on Bluesky Groovy on Mastodon Groovy on LinkedIn Events and conferences Source code on GitHub Report issues in Jira Stack Overflow questions Slack Community You are using an outdated browser. Please upgrade your browser to improve your experience. Apache Groovy&trade; Learn Documentation Download Support Contribute  [...]
+        "content": "The Apache Groovy programming language - Blogs - Reading and Writing CSV files with Groovy&trade; Socialize Discuss on the mailing list Groovy on X Groovy on Bluesky Groovy on Mastodon Groovy on LinkedIn Events and conferences Source code on GitHub Report issues in Jira Stack Overflow questions Slack Community You are using an outdated browser. Please upgrade your browser to improve your experience. Apache Groovy&trade; Learn Documentation Download Support Contribute  [...]
         "url": "blog/reading-and-writing-csv-files.html",
         "site": "dev"
     },
@@ -744,7 +744,7 @@
     {
         "id": "blog/index.html",
         "title": "The Apache Groovy programming language - Blogs",
-        "content": "The Apache Groovy programming language - Blogs Socialize Discuss on the mailing list Groovy on X Groovy on Bluesky Groovy on Mastodon Groovy on LinkedIn Events and conferences Source code on GitHub Report issues in Jira Stack Overflow questions Slack Community You are using an outdated browser. Please upgrade your browser to improve your experience. Apache Groovy&trade; Learn Documentation Download Support Contribute Ecosystem Blog posts Socialize Blogs Reading and Wr [...]
+        "content": "The Apache Groovy programming language - Blogs Socialize Discuss on the mailing list Groovy on X Groovy on Bluesky Groovy on Mastodon Groovy on LinkedIn Events and conferences Source code on GitHub Report issues in Jira Stack Overflow questions Slack Community You are using an outdated browser. Please upgrade your browser to improve your experience. Apache Groovy&trade; Learn Documentation Download Support Contribute Ecosystem Blog posts Socialize Blogs Reading and Wr [...]
         "url": "blog/index.html",
         "site": "dev"
     },