Groovy:有没有一种方法将所有出现的字符串返回为整数偏移量列表?

4
给定一个字符串,我知道Groovy提供了方便的方法,例如
String.findAll(String, Closure)

在字符串中查找正则表达式字符串的所有出现。任何匹配项都将传递给指定的闭包。预计该闭包的第一个参数为完整的匹配项。如果有任何捕获组,它们将放置在后续参数中。

然而,我正在寻找一个类似的方法,其中闭包接收匹配器对象或匹配项的int偏移量。是否有这样的方法?

或者,如果没有:是否有一种常见的方式将给定字符串或模式的所有匹配项的偏移量作为Integers / ints的集合或数组返回?(Commons / Lang或Guava都可以,但我更喜欢纯粹的Groovy)。

2个回答

5
我不知道目前是否有任何方法,但如果您想要的话,可以将该方法添加到String的metaClass中...类似于以下内容:
String.metaClass.allIndexOf { pat ->
  def (ret, idx) = [ [], -2 ]
  while( ( idx = delegate.indexOf( pat, idx + 1 ) ) >= 0 ) {
    ret << idx
  }
  ret
}

可以通过以下方式调用:

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

并返回(在这种情况下)。
[4, 20, 40, 41, 46]

编辑

实际上...一个能够使用正则表达式参数的版本应该是:

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

然后可以这样调用:

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

提供:

[6, 32]

编辑2

最后,将此代码作为一种类别。

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]/ )
}

谢谢(+1)。假设我有一个测试类,它需要在每个方法中使用此功能。我应该把它放在哪里?在静态初始化器中? - Sean Patrick Floyd
1
一旦调用,此方法将对之后创建的每个 String 实例都可用,因此在早期仅调用一次的某个位置是一个不错的选择。为了避免污染 String 的元类,您也可以将其作为类别进行处理,但是您需要执行以下操作:use(MyCategory) {"a string".allIndexOf 's'} - tim_yates
哇,我以前从未听说过“Categories”,这太酷了!(http://docs.codehaus.org/display/GROOVY/Groovy+Categories) - Sean Patrick Floyd
@sean 它们是一种非常好的方式,可以在不过度污染 metaClass 的情况下添加功能。我已将代码作为答案的类别添加了 :-) - tim_yates

3
我猜应该是这样的:

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
}

如果您需要这个功能,那么这个示例可以完美地胜任。因为它返回的结果是

[23, 26, 28, 34, 37]

在 Groovy 控制台中


不错的工作解决方案,谢谢(+1),但我正在寻找更加简洁的东西。 - Sean Patrick Floyd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接