更新“它”在 Groovy 闭包内

发布于 2024-10-12 11:00:29 字数 313 浏览 4 评论 0原文

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

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

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

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

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

谢谢。

I have a domain class that is just a list of strings (youtubeLinks).

When saving these links I want to strip out the video ID and save it instead of the entire URL entered on the UI side.

This is what I'm trying (ignore that the regex is flawed)

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

When I save this, it saves the original value of "it". Is there a way to update this reference and have it save properly?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

流绪微梦 2024-10-19 11:00:30

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

当您需要以某种方式修改集合中的每个元素时,惯用的 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 的博客有一些很好的例子您可能会发现有用的 Groovy 模式匹配。

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

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

or

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

or this (虽然有点做作)

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

Groovy's each loop is merely an iterator, and as such it neither affects the collection on which it operates, nor returns a value of its own. It's basically equivalent to Java's "advanced for loop (for-each)," only with the convenience of dynamic typing and an implicit loop variable (it). While it can be modified, it's a futile enterprise, as you'd be simply changing a reference to the original value, not the value itself. See this question for more on that.

When you need to modify every element within a collection somehow, the idiomatic Groovy (Grails) solution is to use the collect method. Collect transforms each element via the closure you provide, ultimately returning a new collection ( so, it doesn't actually "modify" anything).

Basically, you'll probably want to do something like this:

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"]

..Though there are actually a number of ways one could go about such a task in Groovy.

Additionally, Ted Naleid's blog has some nice examples of Groovy pattern matching that you may find useful.

Edit
Here are several ways in which you could abbreviate the solution you submitted:

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

or

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

or this (Though it's a little contrived)

youtubeLinks = youtubeLinks.join('\n').replaceAll(/.*\?v=/, '').split()
滿滿的愛 2024-10-19 11:00:30

你是对的,最终就像

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

谢谢,诺瑟弗。

You were right, it ended up being like

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

Thanks, Northover.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文