2009-07-02 15 views
23

Ben bir tamsayı değeri içerebilir bir dize eşleşen bir yol arıyorum. Eğer öyleyse, onu ayrıştırın.Scala: bir tam sayı dizesi eşleştir ve ayrıştır?

def getValue(s: String): Int = s match { 
     case "inf" => Integer.MAX_VALUE 
     case Int(x) => x 
     case _ => throw ... 
    } 

amacı dizisi "inf" eşitse, Integer.MAX_VALUE dönmek düşünüyoruz: aşağıdakine benzer bir kod yazmak istiyorum. Dize ayrılabilir bir tamsayıysa, tamsayı değerini döndürün. Aksi halde atın.

cevap

38

Bir bekçi kullanabilirsiniz bir aspiratör

object Int { 
    def unapply(s : String) : Option[Int] = try { 
    Some(s.toInt) 
    } catch { 
    case _ : java.lang.NumberFormatException => None 
    } 
} 

Sizin örnek yöntemi

def getValue(s: String): Int = s match { 
    case "inf" => Integer.MAX_VALUE 
    case Int(x) => x 
    case _ => error("not a number") 
} 

tanımlayın Ve o

scala> getValue("4") 
res5: Int = 4 

scala> getValue("inf") 
res6: Int = 2147483647 

scala> getValue("helloworld") 
java.lang.RuntimeException: not a number 
at scala.Predef$.error(Predef.scala:76) 
at .getValue(<console>:8) 
at .<init>(<console>:7) 
at .<clinit>(<console>) 
at RequestResult$.<init>(<console>:4) 
at RequestResult$.<clinit>(<console>) 
at RequestResult$result(<console>) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(Na... 
+0

Böylece bir nesneyi {} bu şekilde açabilir ve varolan yöntemlere ekleyebilirsiniz. sınıf? Cool (sanırım ...). –

+0

Aldırma, ben {} şimdi bu nesne Int anlamasına ad alanında yeni bir Int sınıfını yaratıyor. –

+3

Aslında oldukça özel durumu yakalamak yerine, dize içeriğini eşleşecek normal ifadeler kullanmak daha verimli olabilir. –

1
def getValue(s: String): Int = s match { 
    case "inf" => Integer.MAX_VALUE 
    case _ => s.toInt 
} 


println(getValue("3")) 
println(getValue("inf")) 
try { 
    println(getValue("x")) 
} 
catch { 
    case e => println("got exception", e) 
    // throws a java.lang.NumberFormatException which seems appropriate 
} 
+0

Bu, anında gereksinimlerimi karşılamak için iyi bir yoldur, ancak aradığım genel çözüm değildir. def doSomething (ler: String): Int = s maç { vaka Int (x) => println ("Bir var Örneğin, belki bir blok dize kadar çözümlenebilir olduğunu türüne bağlı olarak yürütmek isteyeyim int ") kasa Float (x) => println (" bir floatın var ") case _ => throw ... } –

8

kullanarak:

Bu eski olduğunu biliyoruz
def getValue(s: String): Int = s match { 
    case "inf" => Integer.MAX_VALUE 
    case _ if s.matches("[+-]?\\d+") => Integer.parseInt(s) 
} 
9

, soruyu yanıtladı ama bu daha iyi IMHO olduğunu:

Tabii
scala> :paste 
// Entering paste mode (ctrl-D to finish) 

val IntRegEx = "(\\d+)".r 
def getValue(s: String): Option[Int] = s match { 
    case "inf" => Some(Integer.MAX_VALUE) 
    case IntRegEx(num) => Some(num.toInt) 
    case _ => None 
} 

// Exiting paste mode, now interpreting. 

IntRegEx: scala.util.matching.Regex = (\d+) 
getValue: (s: String)Option[Int] 

scala> getValue("inf") 
res21: Option[Int] = Some(2147483647) 

scala> getValue("123412") 
res22: Option[Int] = Some(123412) 

scala> getValue("not-a-number") 
res23: Option[Int] = None 

, herhangi bir özel durumlar durum değil, ama sen gerçekten istiyorsan, sen

kullanabilir
getValue(someStr) getOrElse error("NaN") 
4

ne dersiniz: James Iry en çıkartma cihazının

def readIntOpt(x: String) = 
    if (x == "inf") 
    Some(Integer.MAX_VALUE) 
    else 
    scala.util.Try(x.toInt).toOption 
1

geliştirilmiş bir sürümü:

object Int { 
    def unapply(s: String) = scala.util.Try(s.toInt).toOption 
}