问题描述
我的要求是从src-resourses文件夹中读取csv文件并将其转换为DF。我的代码如下。 流派和月份是案例类,正在使用它为列表提供结构,以便将它们转换为DF。在下面的代码中,应替换_以便我可以使用List [Genre]或List [Month ] 基于将要传递的fileName值。
trait IndexReader[T] {
def read(filePath: String,sep: String,fileName:String): List[T] = {
val stream: InputStream = getClass.getResourceAsstream("/" + filePath)
val lines: Iterator[String] = scala.io.source.fromInputStream(stream).getLines
lines.map(line => {normalize(line,sep,fileName)}).toList
}
def normalize(line: String,fileName:String): T
}
class BrandReader extends IndexReader[_] {
override def normalize(line: String,fileName:String):_ = {
val linesplit: Seq[String] = line.split(sep).toList
val file = fileName match {
case "indexGenre" => Genre(linesplit(0),linesplit(1))
case "indexMonth" => Month(linesplit(0),linesplit(1))
}
file
}
}
解决方法
模式匹配不能从不同分支返回不同类型。
如果您可以定义两个案例类扩展的特征,则可以尝试
sealed trait GenreOrMonth
case class Genre(s: String,s1: String) extends GenreOrMonth
case class Month(s: String,s1: String) extends GenreOrMonth
class BrandReader extends IndexReader[GenreOrMonth] {
override def normalize(line: String,sep: String,fileName: String): GenreOrMonth = ...
}
否则返回类型仅为Product
class BrandReader extends IndexReader[Product] {
override def normalize(line: String,fileName: String): Product = ...
}
或Any
class BrandReader extends IndexReader[Any] {
override def normalize(line: String,fileName: String): Any = ...
}
另一种选择是使用Either
case class Genre(s: String,s1: String)
case class Month(s: String,s1: String)
class BrandReader extends IndexReader[Either[Genre,Month]] {
override def normalize(line: String,fileName:String): Either[Genre,Month] = {
val lineSplit: Seq[String] = line.split(sep).toList
val file = fileName match {
case "indexGenre" => Left(Genre(lineSplit(0),lineSplit(1)))
case "indexMonth" => Right(Month(lineSplit(0),lineSplit(1)))
}
file
}
}
How to define "type disjunction" (union types)?
,这是一个使用无形的想法;我简化了您的操作,因此可以提供一个可运行的示例。我在下面显示代码,或单击链接以查看其运行情况。
https://scalafiddle.io/sf/BhyfPyu/1
import shapeless._
case class Genre(category:String,category2:String)
case class Month(month:String,year:String)
abstract class Reader {
def read: (String,String) = ("String1","String2")
val genTuple = Generic[(String,String)]
def readT[T](implicit genT:Generic.Aux[T,String :: String :: HNil]): T= {
val hList: (String :: String :: HNil) = genTuple.to(read)
genT.from(hList)
}
def main(s:String) = {
s match {
case "GENRE" => readT[Genre]
case "MONTH" => readT[Month]
case _ => throw new IllegalArgumentException(s"$s not supported")
}
}
}
object ReaderImpl extends Reader
println(ReaderImpl.main("GENRE"))
println(ReaderImpl.main("MONTH"))