Преобразование значения в зависимости от типа в SparkSQL через сопоставление типов регистров
можно ли сопоставить параметрический тип в Scala? Допустим у меня есть функция, которая получает два параметра:value
и type
. Я хотел бы использовать сопоставление шаблонов для преобразования типов.
что-то вроде этого:
datatype match {
case IntegerType => return value.toInt
case FloatType => return value.toFloat
case StringType => return value
case DecimalType(_,_) => return BigDecimal(value) // this is not working
case _ => return strrepr
}
здесь DecimalType
принимает два параметра для указания точности требуемой точности. Это может быть, например:
org.apache.spark.sql.types.DecimalType = DecimalType(10,2)
Я пробовал несколько вариантов, и ничего не кажется работа:
-
на
case DecimalType => return BigDecimal(value)
я:error: pattern type is incompatible with expected type; found : org.apache.spark.sql.types.DecimalType.type required: org.apache.spark.sql.types.DataType Note: if you intended to match against the class, try `case DecimalType(_,_)`
-
на
case DecimalType(_,_) => return BigDecimal(value)
я:error: result type Boolean of unapply defined in method unapply in object DecimalType does not conform to Option[_] or Boolean
-
на
case DecimalType[_,_] => return BigDecimal(value)
я:error: org.apache.spark.sql.types.DecimalType does not take type parameters
2 ответов
проблема заключается в использовании return
в коде. Вы сказали, что используете этот фрагмент кода в какой-то функции. Что возвращаемый тип этой функции? Очевидно, вы предполагаете, что иногда это целое число, иногда строка, иногда BigDecimal; но если вы используете return
, он будет искать тип возвращаемого объекта, чтобы определить возвращаемый тип функции. В общем, вы должны сильно избегать использования return
в коде на Scala. Последнее оцененное значение в теле функции возвращенный. Единственный случай использования return
- это когда вы хотите принудительно вернуть значение где-то еще в теле функции. Но все же лучшим способом было бы сохранить возвращаемый объект в переменной и просто оценить эту переменную в последней строке тела функции. И никогда не используйте return!
без return
он работает
scala> val datatype = DecimalType(10, 2)
datatype: org.apache.spark.sql.types.DecimalType = DecimalType(10,2)
scala> val value = BigDecimal(10)
value: scala.math.BigDecimal = 10
scala> datatype match {case DecimalType(_,_) => value}
res150: scala.math.BigDecimal = 10
** проблемы с возвратом **
scala> def test = {datatype match {case DecimalType(_,_) => return value}}
<console>:138: error: method test has return statement; needs result type
def test = {datatype match {case DecimalType(_,_) => return value}}
scala> def test:BigDecimal = {datatype match {case DecimalType(_,_) => return value}}
test: BigDecimal
scala> def test:DataType = {datatype match {case DecimalType(_,_) => return value}}
<console>:138: error: type mismatch;
found : scala.math.BigDecimal
required: org.apache.spark.sql.types.DataType
def test:DataType = {datatype match {case DecimalType(_,_) => return value}}
scala> def test3 = {datatype match {case DecimalType(_,_) => value}}
test3: scala.math.BigDecimal
оказывается, что DecimalType только шаблон соответствует нулевым аргументам:
case DecimalType() => ...
Если вам нужна точность и масштаб, вы должны определить тип случая и вручную извлечь их:
datatype match {
case dt: DecimalType =>
val precision = dt.precision
val scale = dt.scale
...