You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Paul King (Jira)" <ji...@apache.org> on 2026/04/24 20:47:00 UTC
[jira] [Updated] (GROOVY-11958) Add SGM#findGroups/findAllGroups
[ https://issues.apache.org/jira/browse/GROOVY-11958?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Paul King updated GROOVY-11958:
-------------------------------
Description:
*findGroups* (first match with capture groups)
Closest existing Groovy idiom:
{code:groovy}
def m = "New York, NY 10292-0098" =~ /(\d{5})-(\d{4})/
def (all, zip, plus4) = m ? m[0] : [null, null, null]
{code}
With findGroups:
{code:groovy}
def (all, zip, plus4) = "New York, NY 10292-0098".findGroups(/(\d{5})-(\d{4})/)
{code}
findGroups returns an empty list on no match, and Groovy's multi-assign pads missing elements with null, so the ternary/Elvis guard disappears.
*findAllGroups* (all matches with capture groups)
Closest existing Groovy idiom (findAll with a closure couples match extraction and transformation):
{code:groovy}
def pairs = input.findAll(/Type=(\w+) Price=([\d.]+)/) { all, t, p -> "$t:$p" }
{code}
With findAllGroups:
{code:groovy}
def pairs = input.findAllGroups(/Type=(\w+) Price=([\d.]+)/).collect { all, t, p -> "$t:$p" }
{code}
For a one-shot collect the existing findAll-with-closure form is shorter. findAllGroups pays off when you want the raw capture data first and then filter, take, groupBy, or iterate over it separately — the match step and the transform step are decoupled. eachMatch with a closure is the side-effect equivalent; findAll with a closure is the value-returning equivalent that findAllGroups most directly parallels.
> Add SGM#findGroups/findAllGroups
> --------------------------------
>
> Key: GROOVY-11958
> URL: https://issues.apache.org/jira/browse/GROOVY-11958
> Project: Groovy
> Issue Type: Improvement
> Reporter: Paul King
> Assignee: Paul King
> Priority: Major
>
> *findGroups* (first match with capture groups)
> Closest existing Groovy idiom:
> {code:groovy}
> def m = "New York, NY 10292-0098" =~ /(\d{5})-(\d{4})/
> def (all, zip, plus4) = m ? m[0] : [null, null, null]
> {code}
> With findGroups:
> {code:groovy}
> def (all, zip, plus4) = "New York, NY 10292-0098".findGroups(/(\d{5})-(\d{4})/)
> {code}
> findGroups returns an empty list on no match, and Groovy's multi-assign pads missing elements with null, so the ternary/Elvis guard disappears.
> *findAllGroups* (all matches with capture groups)
> Closest existing Groovy idiom (findAll with a closure couples match extraction and transformation):
> {code:groovy}
> def pairs = input.findAll(/Type=(\w+) Price=([\d.]+)/) { all, t, p -> "$t:$p" }
> {code}
> With findAllGroups:
> {code:groovy}
> def pairs = input.findAllGroups(/Type=(\w+) Price=([\d.]+)/).collect { all, t, p -> "$t:$p" }
> {code}
> For a one-shot collect the existing findAll-with-closure form is shorter. findAllGroups pays off when you want the raw capture data first and then filter, take, groupBy, or iterate over it separately — the match step and the transform step are decoupled. eachMatch with a closure is the side-effect equivalent; findAll with a closure is the value-returning equivalent that findAllGroups most directly parallels.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)