2017-06-12 30 views
0

比方说,我有以下的元组斯卡拉消除的if else语句,并以功能性的方式写

(colType, colDocV) 

凡colType是一个布尔值和colDocV是根据这两个值的字符串 ,我会申请一些块将转换应用于Dataframe的代码。

现在,这段代码有效。但是,我不相信这是编写函数式编程代码的正确方法。 我不知道这三种方法中的哪一种可以提高代码的质量,并删除所有if-if else-else: 我应该应用某种设计模式和哪一种? 我应该使用某种模式匹配吗? 我应该使用一些匿名函数吗?

if (colDocV) { 
    val newCol = udf(UDFHashCode.udfHashCode).apply(col(columnName)) 
    dataframe.withColumn(columnName, newCol) 
} else if (colType.contains("string") || colType.contains("text")) { 
    val newCol = udf(Entropy.stringEntropyFunc).apply(col(columnName)).cast(DoubleType) 
    dataframe.withColumn(columnName, newCol) 
} else if (colType.contains("date")) { 
    val newCol = udf(DateUtils.getTimeAsDoubleFunc).apply(col(columnName)).cast(DoubleType) 
    dataframe.withColumn(columnName, newCol) 
} else if (colType.contains("long")) { 
    dataframe.withColumn(columnName, dataframe(columnName).cast(DoubleType)) 
} else { 
    dataframe.drop(columnName) //Dropping column that cannot be processed 
} 
+0

没有什么“非功能性的”关于使用'如果-else'表达的解决方案理解。要做的更好的事情是传输类型而不是字符串,但这是底层基础架构(Spark中的数据框)所具有的约束条件。也许使用'DataSet [T]'而不是强类型模式(以case类的形式)会减少样板。 –

+0

@YuvalItzchakov他使用了一个if语句,而不是一个表达式,因为它完全依赖于副作用,可以说它是非功能性的。 – Carcigenicate

+0

@Carcigenicate如果我们要准确的话,Scala中没有if语句*,它是*表达式*。除此之外,你在说什么副作用? –

回答

3

您可以用match声明和一堆正则表达式的做到这一点。

val str = ".*(?:string|text).*".r 
val date = ".*date.*".r 
val long = ".*long.*".r 

def col(tuple: (Boolean, String)) = tuple match { 
    case (true, _) => Some(udf(...)) 
    case (_, str()) => Some(udf(...)) 
    case (_, date()) => Some(udf(...)) 
    case (, long()) => Some(udf(...)) 
    case _ => None 
} 
col(colType -> colDocv) 
.fold(dataframe.drop(columnName)) { newCol => 
    dataframe.withColumn(columnName, newCol) 
} 
0

据我从你的问题以下均可使用match case

def callUdf(colDocV: String, colType: Boolean, dataframe: DataFrame) = (colDocV, colType) match { 
    case x if (x._1.contains("string") || x._1.contains("text")) => dataframe.withColumn(columnName, udf(Entropy.stringEntropyFunc).apply(col(columnName)).cast(DoubleType)) 
    case x if (x._1.contains("date")) => dataframe.withColumn(columnName, udf(DateUtils.getTimeAsDoubleFunc).apply(col(columnName)).cast(DoubleType)) 
    case x if (x._1.contains("long")) => dataframe.withColumn(columnName, dataframe(columnName).cast(DoubleType)) 
    case _ => dataframe.drop(columnName) 

}