【问题标题】:Updating "it" inside a Groovy closure在 Groovy 闭包中更新“it”
【发布时间】:2011-06-10 04:18:02
【问题描述】:

我有一个域类,它只是一个字符串列表 (youtubeLinks)。

保存这些链接时,我想去掉视频 ID 并保存它,而不是在 UI 端输入的整个 URL。

这就是我正在尝试的(忽略正则表达式有缺陷)

youtubeLinks.each {
 def youtubeRegex = /v=(.*)/
 def matcher = ( it =~ youtubeRegex )
 it = matcher[0][1]
}

当我保存它时,它会保存“it”的原始值。有没有办法更新此参考并正确保存?

谢谢。

【问题讨论】:

    标签: grails groovy closures


    【解决方案1】:

    Groovy 的each 循环只是一个迭代器,因此它既不会影响它所操作的集合,也不会返回它自己的值。它基本上等同于 Java 的“高级 for 循环(for-each)”,只是具有动态类型的便利性和隐式循环变量(it)。虽然it 可以修改,但它是徒劳的,因为您只是更改对原始值的引用,而不是值本身。有关更多信息,请参阅this question

    当您需要以某种方式修改集合中的每个元素时,惯用的 Groovy (Grails) 解决方案是使用 collect 方法。 Collect 通过您提供的闭包转换每个元素,最终返回一个新集合(因此,它实际上并没有“修改”任何东西)。

    基本上,您可能想要做这样的事情:

    def links = '''http://www.youtube.com/watch?v=fl6s1x9j4QQ
    http://www.youtube.com/watch?v=tCvMKcNJCAY
    '''
    
    assert (links =~ /watch\?v=(.*)/).collect{match -> match[1]} == ["fl6s1x9j4QQ", "tCvMKcNJCAY"]
    

    ..虽然在 Groovy 中实际上有很多方法可以完成这样的任务。

    此外,Ted Naleid's blog 有一些很好的 Groovy 模式匹配示例,您可能会发现它们很有用。

    编辑 您可以通过以下几种方式来缩写您提交的解决方案:

    youtubeLinks = youtubeLinks.collect{link -> (link =~ /\?v=(.*)$/)[0][1]}
    

    youtubeLinks = youtubeLinks.collect{link -> link.replaceAll(/^.*\?v=/, "") }
    

    或者这个(虽然有点做作)

    youtubeLinks = youtubeLinks.join('\n').replaceAll(/.*\?v=/, '').split()
    

    【讨论】:

    • 谢谢!我会检查一下。
    • 很酷的答案。但是第二个链接上的视频已经被删除了=(
    【解决方案2】:

    你是对的,结果是这样的

    youtubeLinks = youtubeLinks.collect {
        def youtubeRegex = /v=(.*)[&]/
        def matcher = ( it =~ youtubeRegex )
        return matcher[0][1]
    }
    

    谢谢,Northover。

    【讨论】:

    • 很高兴我能帮上忙。如果您对整合代码的方式感兴趣,我已经为我的答案添加了一些额外的工作解决方案。干杯。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 2021-10-21
    • 2012-03-31
    • 2011-01-02
    • 1970-01-01
    相关资源
    最近更新 更多