2017-06-12 27 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) 

}