Groovy: is there any way to return all occurrences of a string in a list of integer offsets?

Given a string, I know Groovy provides convenience methods like String.findAll(String, Closure)

Finds all occurrences of a regular string expression inside a string. Any matches are passed to the specified closure. The closure is expected to have a full match in the first setting. If there is a capture of groups, they will be placed in the following parameters.

However, I am looking for a similar method when a closure gets either a Matcher object or an int offset to match. Is there such a beast?

Or, if not: is there a general way to return the offsets of all matches for a given string or template as a collection or an array of integers / ints? (Commons / Lang or Guava are both fine, but I would prefer just Groovy.)

+4
source share
2 answers

I don't know anything that currently exists, but you can add this method to metaClass from String if you want ... Something like:

 String.metaClass.allIndexOf { pat -> def (ret, idx) = [ [], -2 ] while( ( idx = delegate.indexOf( pat, idx + 1 ) ) >= 0 ) { ret << idx } ret } 

Which can be called:

 "Finds all occurrences of a regular expression string".allIndexOf 's' 

and returns (in this case)

 [4, 20, 40, 41, 46] 

Edit

Actually ... a version that can work with regex options will be:

 String.metaClass.allIndexOf { pat -> def ret = [] delegate.findAll pat, { s -> def idx = -2 while( ( idx = delegate.indexOf( s, idx + 1 ) ) >= 0 ) { ret << idx } } ret } 

which can then be called as:

 "Finds all occurrences of a regular expression string".allIndexOf( /a[lr]/ ) 

:

 [6, 32] 

Edit 2

And finally, this code as a category

 class MyStringUtils { static List allIndexOf( String str, pattern ) { def ret = [] str.findAll pattern, { s -> def idx = -2 while( ( idx = str.indexOf( s, idx + 1 ) ) >= 0 ) { ret << idx } } ret } } use( MyStringUtils ) { "Finds all occurrences of a regular expression string".allIndexOf( /a[lr]/ ) } 
+5
source

I think something like

 def str = " a long string with some regexpable text in" def lastIndex = 0 def indexes = str.findAll(~/e/) { match -> lastIndex = str.indexOf(match, lastIndex+1) return lastIndex } 

will do the job perfectly, as this example returns

 [23, 26, 28, 34, 37] 

in Groovy Console

+3
source

Source: https://habr.com/ru/post/1337450/


All Articles