2014-05-08 43 views
6

什麼是快速 a 安全如何將字符串轉換爲數字類型,同時在轉換失敗時提供默認值?從字符串到數字類型的快速安全轉換

我使用的通常推薦的方法,使用異常即嘗試:

implicit class StringConversion(val s: String) { 

    private def toTypeOrElse[T](convert: String=>T, defaultVal: T) = try { 
    convert(s) 
    } catch { 
    case _: NumberFormatException => defaultVal 
    } 

    def toShortOrElse(defaultVal: Short = 0) = toTypeOrElse[Short](_.toShort, defaultVal) 
    def toByteOrElse(defaultVal: Byte = 0) = toTypeOrElse[Byte](_.toByte, defaultVal) 
    def toIntOrElse(defaultVal: Int = 0) = toTypeOrElse[Int](_.toInt, defaultVal) 
    def toDoubleOrElse(defaultVal: Double = 0D) = toTypeOrElse[Double](_.toDouble, defaultVal) 
    def toLongOrElse(defaultVal: Long = 0L) = toTypeOrElse[Long](_.toLong, defaultVal) 
    def toFloatOrElse(defaultVal: Float = 0F) = toTypeOrElse[Float](_.toFloat, defaultVal) 
} 

使用這個工具類,我可以在任何字符串現在可以輕鬆地轉換成一個給定的數字類型,並在案件提供一個默認值的字符串沒有正確表示數值類型:

scala> "123".toIntOrElse() 
res1: Int = 123 
scala> "abc".toIntOrElse(-1) 
res2: Int = -1 
scala> "abc".toIntOrElse() 
res3: Int = 0 
scala> "3.14159".toDoubleOrElse() 
res4: Double = 3.14159 
... 

雖然它精美的作品,這種做法似乎並沒有很好地擴展,可能是例外機制的原因是:

scala> for (i<-1 to 10000000) "1234".toIntOrElse() 

需要大約1秒執行而

scala> for (i<-1 to 10000000) "abcd".toIntOrElse() 

需要大約1分鐘

我想另一種方法是避免依賴由toInt,toDouble,...方法觸發的異常。

這可以通過檢查一個字符串「是給定類型」來實現嗎? 當然,人們可以遍歷字符串字符並檢查它們是否是數字(例如參見this example),但其他數字格式(double,float,hex,octal,...)呢?

+1

正則表達式可能是你最好的方式去這裏,如果你完全想避免overhea d的try/catch語義。你只需要爲你想要轉換的每種可能的數字類型提供正則表達式。但說實話,這可能是一個不成熟的優化。這段代碼需要多快?它多久打一次?它多久會得到一個無效數字,這會觸發catch塊?這些問題在優化之前需要問自己,因爲代碼變得更復雜一些。 – cmbaxter

+0

@cmbaxter我同意你的看法,但我在大數據上下文中使用它,我在這裏解析大量的CSV文件(數十億行),所以它很重要。 – borck

+0

夠公平的。然後我會用正則表達式首先審查字符串。會更快。 – cmbaxter

回答

1

作爲第一種方法,篩選出不包含任何位數

private def toTypeOrElse[T](convert: String=>T, defaultVal: T) = try { 
    if (s.contains("[0-9]")) convert(s) { 
    else defaultVal 
    } catch { 
    case _: NumberFormatException => defaultVal 
    } 
} 

更新這些輸入字符串

富含組中的數值時可能出現的字符,但沒有秩序的在重複考慮發生或限制,

private def toTypeOrElse[T](convert: String=>T, defaultVal: T) = try { 
    if (s matches "[\\+\\-0-9.e]+") convert(s) 
    else defaultVal 
    } catch { 
    case _: NumberFormatException => defaultVal 
    } 
} 
+0

爲什麼不過濾掉那些不包含數字或'-'的數字呢? – Kigyo

相關問題