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)