如何从Scala中的方法返回案例类列表

问题描述

我的要求是从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"))