Groovy:如何检查列表是否包含另一个包含正则表达式格式的列表中的项目

时间:2018-10-22 00:13:37

标签: regex list groovy

已经给了我两个列表,我需要检查站点列表中是否有任何项目位于被忽略的站点中。当我运行下面的代码时,它只会打印出google.co.uk,但是是否还应该打印出amazon.co.uk和groovy-lang.org?

有人可以解释为什么不

def ignoredSites = ["www.amazon.com", /amazon.co.*/, /www.scala-lang.org/,/google.co.uk/, ~/htt(p|ps):\/\/www\.amazon\.co.*/, "groovy-lang.org"]
def sites = ["amazon.co.uk", ~/groo{2}vy-lang\.org/, "google.co.uk", "amazon.com", ~/scala.*/]


sites.each { site ->
    ignoredSites.contains(site) ? println("Ignored: ${site}") : ""
}

3 个答案:

答案 0 :(得分:2)

首先,您要在数组中混合正则表达式和字符串。我建议您将它们放在单独的列表中。 第二,要注意时髦的斜线弦。

我修改了您的代码,以使您看到slashy strings(amazon.co。*,www.scala-lang.org,google.co.uk)实际上被解释为字符串,而不是预期的正则表达式

在您的情况下,由于您要在数组中混合正则表达式和字符串,因此必须以其他方式进行检查:

def ignoredSites = ["www.amazon.com", /amazon.co.*/, /www.scala-lang.org/,/google.co.uk/, ~/htt(p|ps):\/\/www\.amazon\.co.*/, "groovy-lang.org"]
def sites = ["amazon.co.uk", ~/groo{2}vy-lang\.org/, "google.co.uk", "amazon.com", ~/scala.*/]


println '==========sites============'
sites.each { site ->
  println site.toString() + " == "+ site.class
}
println '==========ignoredSites============'
ignoredSites.each { site ->
  println site.toString() + " == "+ site.class
}
println '======================'

sites.each { site ->
     if(site.class.equals(java.util.regex.Pattern)){
       ignoredSites.each{ is ->
         if(is.class.equals(java.lang.String)){
           if(is.matches(site)) println("Ignored: ${site}") //string = regex
         } else {
           //can't match 2 regex
         }
       }
     } else {
       ignoredSites.each{ is ->
         if(is.class.equals(java.lang.String)){
           if(is.equals(site)) println("Ignored: ${site}") //string = regex
         } else {
           if(site.matches(is)) println("Ignored3: ${site}") //string = regex
         }
       }
     }
}

已编辑

如果运行带有打印元素类型的代码,则会注意到以下内容:

==========sites============
amazon.co.uk == class java.lang.String
groo{2}vy-lang\.org == class java.util.regex.Pattern
google.co.uk == class java.lang.String
amazon.com == class java.lang.String
scala.* == class java.util.regex.Pattern
==========ignoredSites============
www.amazon.com == class java.lang.String
amazon.co.* == class java.lang.String
www.scala-lang.org == class java.lang.String
google.co.uk == class java.lang.String
htt(p|ps)://www\.amazon\.co.* == class java.util.regex.Pattern
groovy-lang.org == class java.lang.String
======================

因此,amazon.co.uk不匹配,因为应与之匹配的正则表达式:

amazon.co.* == class java.lang.String
由于斜线,

被常规用法解释为字符串。 另一方面

groo{2}vy-lang\.org == class java.util.regex.Pattern

是一个正则表达式,但是其中的{2}表示o正好出现2次。 简而言之,groo{2}vy-lang\.org将与grooovy-lang.org相匹配(请注意其中的三个o)。

答案 1 :(得分:2)

以网站为模式,但假设这就是您的意思,这是非常不寻常的:

def ignoredSites = ["www.amazon.com", /amazon.co.*/, /www.scala-lang.org/,/google.co.uk/, ~/htt(p|ps):\/\/www\.amazon\.co.*/, "groovy-lang.org"]
def sites = ["amazon.co.uk", ~/gro{2}vy-lang\.org/, "google.co.uk", "amazon.com", ~/scala.*/]

sites.findAll { site ->
    ignoredSites.find{ it == site || (site in String && site.matches(it) || (it in String && it.matches(site))) }
}.each{ println "Ignored: $it" }

答案 2 :(得分:1)

实际上,我不同意已接受的答案,这似乎是面试官希望您陷入的陷阱。

要对此进行检查,您可以将~/groo{2}vy-lang\.org/更改为~/gro{2}vy-lang\.org/,然后亲自查看"groovy-lang.org"仍然会被忽略。

这是因为java.util.Collection.contains()并没有变得聪明(可能是因为它没有被Groovy覆盖),并且在这种特殊情况下只是检查是否相等(定义为here)。

因此"groovy-lang.org" ==~ /gro{2}vy-lang.org/(模式匹配)但是"groovy-lang.org" != ~/gro{2}vy-lang.org/(它们不是相等的对象,而groovy truth没有抽象出该特定情况)。

“忽略”测试基于对象相等性,而不是基于模式匹配,因为访问员可能会自愿误导您相信。

希望这会有所帮助,而且我没有记错。