如何将数据从重复的列表数据转换为组数据列表

时间:2019-05-17 04:09:04

标签: java scala list dictionary

问题是来自class OldCompanyMovie(ocm : List[(company:String, movie:String, actor:String)])

的地图数据

List[CompanyMovie(company:String, movies: List[Movies(movie:String, actors : List[actor:String])])]

说明: 同一部电影中男主角的名字应该是电影中的男主角,例如class Movies(movie: String, actors: List[actor:String])

与列表演员相同,电影应该是CompanyMovie(company: String, movies : List[movie:Movies]))这样的公司中的电影列表

总体应为List[CompanyMovie(company:String, Movies(mv : List[movie:String, List[actor:String]]))]

*更新 我已经尝试了整整一天,所以结果差强人意但效果可能不佳

val companies: List[Company] = oldWorldMovieList.map { item =>
              val moviesOfeachCompany: List[Option[Pattern]] = oldWorldMovieList.map { oldWML =>
                if (item.company == oldWML.company) {
                    val actorsOfeachMovie: List[Option[String]] = oldWorldMovieList.map { oldWML2 => 
                      if (item.movie == oldWML2.movie) {
                        Some(oldWML2.actor)
                      } else None
                    }.distinct
                    Some(Pattern(item.movie, actorsOfeachMovie))
                } else None
              }.distinct
              Company(item.company, moviesOfeachCompany)
            }.distinct
            val worldMovies: WorldMovies = WorldMovies(companies)

ps。我无法更改源数据的模式。

如果是杰森(Json)就像这样List[String, String, String]

[{"company":"Marvel","movie":"Avengers","actor":"ROBERT DOWNEY JR."},{"company":"Marvel","movie":"Avengers","actor":"CHRIS EVANS"},{"company":"Marvel","movie":"Avengers","actor":"MARK RUFFALO"},{"movie":"Marvel","movie":"Guardian of the galaxy","actor":"KAREN GILLAN"},{"company":"Marvel","movie":"Guardian of the galaxy","actor":"ZOE SALDANA"},{"company":"dc","movie":"Batman","actor":"CHRISTIAN BALE"},{"company":"dc","movie":"Batman","actor":"CHRISTOPHER REEVE"}]

转换后应该是这个

[{"company": "Marvel", "movies" : [{"movie": "Avengers", "actor": ["ROBERT DOWNEY JR.", "CHRIS EVANS", "MARK RUFFALO"]},{"movie": "Guardian of the galaxy", "actor": ["KAREN GILLAN", "ZOE SALDANA"]}]},{"company": "dc","movies" : [{"movie": "Batman", "actor": ["CHRISTOPHER REEVE", "CHRISTIAN BALE"]}]}]

3 个答案:

答案 0 :(得分:1)

类似于Norwæ解决方案,但(IMHO)更简单直接。
另外,由于它也使用Iterators,因此性能可能更高。

final case class OldModel(company: String, movie: String, actor: String)
final case class Company(name: String, movies: List[Movie])
final case class Movie(name: String, actors: List[String])

def toNewModel(oldData: List[OldModel]): List[Company] =
  oldData
    .groupBy(_.company)
    .iterator
    .map { case (company, group) =>
      val movies =
        group
          .groupBy(_.movie)
          .iterator
          .map { case (movie, group) =>
            val actors = group.map(_.actor)
            Movie(movie, actors)
          }.toList
      Company(company, movies)
    }.toList

答案 1 :(得分:0)

我的尝试。我不确定这是一个好习惯。

val companies: List[Company] = oldWorldMovieList.map { item =>
          val moviesOfeachCompany: List[Option[Pattern]] = oldWorldMovieList.map { oldWML =>
            if (item.company == oldWML.company) {
                val actorsOfeachMovie: List[Option[String]] = oldWorldMovieList.map { oldWML2 => 
                  if (item.movie == oldWML2.movie) {
                    Some(oldWML2.actor)
                  } else None
                }.distinct
                Some(Pattern(item.movie, actorsOfeachMovie))
            } else None
          }.distinct
          Company(item.company, moviesOfeachCompany)
        }.distinct
        val worldMovies: WorldMovies = WorldMovies(companies)

答案 2 :(得分:0)

我认为您可以使用groupBy非常优雅地做到这一点。例如:

case class CompanyMovie(company: String, movies: Seq[Movie])
case class Movie(name: String, actors: Seq[String])

def convert(in: Seq[(String, String, String)]): Seq[CompanyMovie] = {
  val byCompany = in.groupBy(_._1)
  val byCompanyAndMovie = byCompany.mapValues(_.groupBy(_._2).toSeq)
  byCompanyAndMovie.toSeq.map {
    case (company, rawMovies) => 
      val movies = rawMovies.map {
        case (name, t) => Movie(name, t.map(_._3))
      }

      CompanyMovie(company, movies)
  }
}