2011-11-28 33 views
28

Tôi thường xuyên đối sánh các chuỗi với các cụm từ thông dụng. Trong Java:..Kết hợp với cụm từ thông dụng trong Scala

java.util.regex.Pattern.compile ("\ w +") khớp ("this_is") phù hợp với

Ouch. Scala có nhiều lựa chọn thay thế.

  1. "\\w+".r.pattern.matcher("this_is").matches
  2. "this_is".matches("\\w+")
  3. "\\w+".r unapplySeq "this_is" isDefined
  4. val R = "\\w+".r; "this_is" match { case R() => true; case _ => false}

Đầu tiên là giống như nặng cân như mã Java.

Vấn đề với điều thứ hai là bạn không thể cung cấp mẫu được biên dịch ("this_is".matches("\\w+".r")). (Điều này có vẻ là một anti-pattern vì hầu như mọi khi có một phương thức mà có một regex để biên dịch có một quá tải mà phải mất một regex).

Vấn đề với vấn đề thứ ba là nó lạm dụng unapplySeq và do đó rất khó hiểu.

Thứ tư là tuyệt vời khi phân tách các phần của cụm từ thông dụng, nhưng quá nặng khi bạn chỉ muốn có kết quả boolean.

Tôi có thiếu cách dễ dàng để kiểm tra các kết quả khớp với cụm từ thông dụng không? Có lý do tại sao String#matches(regex: Regex): Boolean không được xác định? Thực tế, ở đâu được xác định là String#matches(uncompiled: String): Boolean?

+3

Cần lưu ý rằng 'Chuỗi # đối sánh (chuỗi: Chuỗi)' không được xác định bởi thông số 2.9 hoặc [StringLike] (http://www.scala-lang.org/api/current/index.html # scala.collection.immutable.StringLike) nhập từ thư viện chuẩn. Đó là, trên thực tế, một tạo phẩm của định nghĩa của [Strings in Java] (http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#matches (java.lang. Chuỗi)). – ig0774

+0

Tôi không hiểu ý bạn là quá nặng trong ví dụ đầu tiên? Bạn có nghĩa là mã quá dài, hoặc bạn có nghĩa là nó làm quá nhiều công việc? –

+1

quá nhiều mã, công việc chính xác là những gì tôi muốn – schmmd

Trả lời

31

Bạn có thể xác định một mô hình như thế này:

scala> val Email = """(\w+)@([\w\.]+)""".r 

findFirstIn sẽ trở lại Some[String] nếu nó phù hợp hoặc khác None.

scala> Email.findFirstIn("[email protected]") 
res1: Option[String] = Some([email protected]) 

scala> Email.findFirstIn("test") 
rest2: Option[String] = None 

Bạn thậm chí có thể trích xuất:

scala> val Email(name, domain) = "[email protected]" 
name: String = test 
domain: String = example.com 

Cuối cùng, bạn cũng có thể sử dụng String.matches phương pháp truyền thống (và thậm chí tái chế trước đó được xác định Email Regexp:.

scala> "[email protected]".matches(Email.toString) 
res6: Boolean = true 

Hy vọng điều này sẽ giúp

+0

Vâng, tôi cho rằng tôi có thể làm '" ""^(\ w +) $ "" ". FindFirstIn (" test_string ")' ... – schmmd

+1

@schmmd đừng quên '.r' để xây dựng một' Regex'. – David

+0

Rất tiếc! nó sẽ không được tốt đẹp để có 'trận đấu' được định nghĩa trong' Regex'? – schmmd

12

Tôi đã tạo một mẫu "Pimp my Library" nhỏ cho vấn đề đó. Có lẽ nó sẽ giúp bạn ra ngoài.

import util.matching.Regex 

object RegexUtils { 
    class RichRegex(self: Regex) { 
    def =~(s: String) = self.pattern.matcher(s).matches 
    } 
    implicit def regexToRichRegex(r: Regex) = new RichRegex(r) 
} 

Ví dụ về sử dụng

scala> import RegexUtils._ 
scala> """\w+""".r =~ "foo" 
res12: Boolean = true 
+1

Tuyệt! Mặc dù tôi muốn gọi toán tử '~' chứ không phải là '~ =' bởi vì toán tử kết thúc bằng '=' nhìn vào tôi như những đột biến tại chỗ (từ C++ và quy ước Python ...). –

+0

Vâng, tôi đang nhắm đến perl's = ~ nhưng rõ ràng là có cái tên. –

+0

Chỉ cần nghĩ rằng tôi muốn đề cập đến Haskell có một toán tử = ~ cho phù hợp với regexes quá. Tôi đã thấy '~ =' được sử dụng để có nghĩa là không bằng, như '! ='. – eriksensei

3

Tôi thường sử dụng

val regex = "...".r 
if (regex.findFirstIn(text).isDefined) ... 

nhưng tôi nghĩ rằng đó là khá vụng về.

Các vấn đề liên quan