繁体   English   中英

如何按 Scala 中元素列表的各个元素进行分组

[英]How can I group by the individual elements of a list of elements in Scala

如果我没有用他们的实际名称命名,请原谅我,我刚刚开始学习 Scala。我已经四处寻找了一段时间,但找不到我的问题的明确答案。

假设我有一个对象列表,每个 object 都有两个字段: x: Intl: List[String] ,在我的例子中,字符串代表类别。

l个列表可以是任意长度,因此一个 object 可以属于多个类别。 此外,各种对象可以属于同一类别。 我的目标是按各个类别对对象进行分组,其中类别是键。 这意味着如果 object 被链接到说“N”个类别,它将出现在“N”个键值对中。

到目前为止,我设法通过以下方式对类别列表进行分组: objectList.groupBy(x => xl)但是,这显然是按类别列表而不是按类别对对象进行分组。

我正在尝试使用不可变的 collections 来避免循环等。

如果有人有一些想法,将不胜感激! 谢谢

编辑:通过请求实际案例 class 和我正在尝试的。 case class Car(make: String, model: String, fuelCapacity: Option[Int], category:Option[List[String]])同样,一辆汽车可以属于多个类别。 比方说List("SUV", "offroad", "family")

我想按category元素而不是整个类别列表进行分组,并将fuelCapacity作为值,以便能够在其他指标中提取每个类别的平均fuelCapacity

像下面这样的东西?

objectList // Seq[YourType]
  .flatMap(o => o.l.map(c => c -> o)) // Seq[(String, YourType)]
  .groupBy { case (c,_) => c } // Map[String,Seq[(String,YourType)]]
  .mapValues { items => c -> items.map { case (_, o) => o } } // Map[String, Seq[YourType]]

(故意“重”来帮助大家理解背后的想法)

编辑,或截至 Scala 2.13 感谢groupMap

objectList // Seq[YourType]
  .flatMap(o => o.l.map(c => c -> o)) // Seq[(String, YourType)]
  .groupMap { case (c,_) => c } { case (_, o) => o } // Map[String,Seq[YourType]]

使用您的编辑作为指南。

case class Car( make: String
              , model: String
              , fuelCapacity: Option[Int]
              , category:Option[List[String]] )

val cars: List[Car] = ???

//all currently known category strings
val cats: Set[String] = cars.flatMap(_.category).flatten.toSet

//category -> list of cars in this category
val catMap: Map[String,List[Car]] =
  cats.map(cat => (cat, cars.filter(_.category.contains(cat)))).toMap

//category -> average fuel capacity for cars in this category 
val fcAvg: Map[String,Double] =
  catMap.map{case (cat, cars) =>
    val fcaps: List[Int] = cars.flatMap(_.fuelCapacity)
    if (fcaps.lengthIs < 1) (cat, -1d)
    else (cat, fcaps.sum.toDouble / fcaps.length)
  }

你非常接近,你只需要在group之前拆分列表中的每个单独元素,所以尝试这样的事情:

// I used a Set instead of a List,
// since I don't think the order of categories matters
// as well I would think having two times the same category doesn't make sense.
final case class MyObject(x: Int, categories: Set[String] = Set.empty) {
  def addCategory(category: String): MyObject =
    this.copy(categories = this.categories + category)
}

def groupByCategories(data: List[MyObject]): Map[String, List[Int]] =
  data
    .flatMap(o => o.categories.map(c => c -> o.x))
    .groupMap(_._1)(_._2)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM