簡體   English   中英

重寫Scala代碼以提高功能性

[英]Rewrite scala code to be more functional

我試圖自學Scala,同時嘗試編寫功能語言慣用的代碼,即編寫更好,更優雅的功能代碼。

我有下面的代碼可以正常工作:

import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame, SparkSession}
import java.time.LocalDate
object DataFrameExtensions_ {
  implicit class DataFrameExtensions(df: DataFrame){
    def featuresGroup1(groupBy: Seq[String], asAt: LocalDate): DataFrame = {df}
    def featuresGroup2(groupBy: Seq[String], asAt: LocalDate): DataFrame = {df}
  }
}
import DataFrameExtensions_._
val spark = SparkSession.builder().config(new SparkConf().setMaster("local[*]")).enableHiveSupport().getOrCreate()
import spark.implicits._
val df = Seq((8, "bat"),(64, "mouse"),(-27, "horse")).toDF("number", "word")
val groupBy = Seq("a","b")
val asAt = LocalDate.now()
val dataFrames = Seq(df.featuresGroup1(groupBy, asAt),df.featuresGroup2(groupBy, asAt))

最后一行雖然困擾我。 這兩個函數( featuresGroup1featuresGroup2 )都具有相同的簽名:

scala> :type df.featuresGroup1(_,_)
(Seq[String], java.time.LocalDate) => org.apache.spark.sql.DataFrame

scala> :type df.featuresGroup2(_,_)
(Seq[String], java.time.LocalDate) => org.apache.spark.sql.DataFrame

並使用與參數相同的val ,因此我假設我可以以一種更具功能性的方式(可能以某種方式使用.map )來寫那行,這意味着我可以只編寫一次參數列表並將其傳遞給兩個函數。 我無法弄清楚語法。 我以為也許可以構造一個這些功能的列表,但這不起作用:

scala> Seq(featuresGroup1, featuresGroup2)
<console>:23: error: not found: value featuresGroup1
       Seq(featuresGroup1, featuresGroup2)
           ^
<console>:23: error: not found: value featuresGroup2
       Seq(featuresGroup1, featuresGroup2)
                           ^

有人可以幫忙嗎?

我以為也許可以構造這些功能的列表,但是那沒用

您需要通過使用下划線運算符來顯式執行eta擴展,以將方法轉換為函數(在Scala中不同)。

val funcs = Seq(featuresGroup1 _, featuresGroup2 _)

或使用占位符:

val funcs = Seq(featuresGroup1(_, _), featuresGroup2(_, _))

而且,使用map運算符絕對正確:

val dataFrames = funcs.map(f => f(groupBy, asAdt))

我強烈建議您不要使用StringSeq類型的隱式Seq ,就好像在多個地方使用它們一樣,它們也會導致細微的錯誤,這些錯誤從代碼中不會立即顯而易見,並且在將代碼移至某個位置時,代碼很容易被破壞。

如果要使用隱式,請將它們包裝到自定義類型中:

case class DfGrouping(groupBy: Seq[String]) extends AnyVal

implicit val grouping: DfGrouping = DfGrouping(Seq("a", "b"))

我以為也許可以構造一個這些功能的列表,但這不起作用:

當上面已經有正確的語法df.featuresGroup1(_,_)時,為什么在這里只寫featuresGroup1/2

Seq(df.featuresGroup1(_,_), df.featuresGroup2(_,_)).map(_(groupBy, asAt))

df.featuresGroup1 _應該工作。

如果您具有預期的類型,則df.featuresGroup1本身可以工作,例如

val dataframes: Seq[(Seq[String], LocalDate) => DataFrame] = 
  Seq(df.featuresGroup1, df.featuresGroup2)

但是在這種特定情況下,提供期望的類型比使用lambda更冗長。

為什么不只是在DataFrameExtensions創建一個函數呢?

def getDataframeGroups(groupBy: Seq[String], asAt: String) = Seq(featuresGroup1(groupBy,asAt), featuresGroup2(groupBy,asAt))

我認為您可以創建如下功能列表:

val funcs:List[DataFrame=>(Seq[String], java.time.LocalDate) => org.apache.spark.sql.DataFrame]  = List(_.featuresGroup1, _.featuresGroup1)
funcs.map(x => x(df)(groupBy, asAt))

似乎您有將一個DataFrame轉換為另一個DataFrame的函數列表。 如果是這樣的話,您可以在ScalazEndo一起Scalaz

我最喜歡這個答案,這是由Alexey Romanov提供的。

import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame, SparkSession}
import java.time.LocalDate
object DataFrameExtensions_ {
  implicit class DataFrameExtensions(df: DataFrame){
    def featuresGroup1(groupBy: Seq[String], asAt: LocalDate): DataFrame = {df}
    def featuresGroup2(groupBy: Seq[String], asAt: LocalDate): DataFrame = {df}
  }
}
import DataFrameExtensions_._
val spark = SparkSession.builder().config(new SparkConf().setMaster("local[*]")).enableHiveSupport().getOrCreate()
import spark.implicits._
val df = Seq((8, "bat"),(64, "mouse"),(-27, "horse")).toDF("number", "word")
val groupBy = Seq("a","b")
val asAt = LocalDate.now()
Seq(df.featuresGroup1(_,_), df.featuresGroup2(_,_)).map(_(groupBy, asAt))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM