Scala 将列表提取到多个不同的列表
如何将Scala列表提取到Scala中具有多个不同列表的列表 从 到 下面是一种(效率相当低)的方法:按值分组,按组大小对结果排序,然后使用第一个组作为原始组每次索引扫描的基础,以构建不同的列表:Scala 将列表提取到多个不同的列表,scala,list,Scala,List,如何将Scala列表提取到Scala中具有多个不同列表的列表 从 到 下面是一种(效率相当低)的方法:按值分组,按组大小对结果排序,然后使用第一个组作为原始组每次索引扫描的基础,以构建不同的列表: scala> val l = List(1,2,6,3,5,4,4,3,4,1) l: List[Int] = List(1, 2, 6, 3, 5, 4, 4, 3, 4, 1) scala> val groups = l.groupBy(identity).values.toList
scala> val l = List(1,2,6,3,5,4,4,3,4,1)
l: List[Int] = List(1, 2, 6, 3, 5, 4, 4, 3, 4, 1)
scala> val groups = l.groupBy(identity).values.toList.sortBy(- _.size)
groups: List[List[Int]] = List(List(4, 4, 4), List(1, 1), List(3, 3), List(5), List(6), List(2))
scala> groups.head.zipWithIndex.map { case (_, i) => groups.flatMap(_.drop(i).headOption) }
res9: List[List[Int]] = List(List(4, 1, 3, 5, 6, 2), List(4, 1, 3), List(4))
这里还有另一个选项-扫描输入N次,其中N是单个值的最大重复次数:
// this function splits input list into two:
// all duplicate values, and the longest list of unique values
def collectDistinct[A](l: List[A]): (List[A], List[A]) = l.foldLeft((List[A](), List[A]())) {
case ((remaining, distinct), candidate) if distinct.contains(candidate) => (candidate :: remaining, distinct)
case ((remaining, distinct), candidate) => (remaining, candidate :: distinct)
}
// this recursive function takes a list of "remaining" values,
// and a list of distinct groups, and adds distinct groups to the list
// until "remaining" is empty
@tailrec
def distinctGroups[A](remaining: List[A], groups: List[List[A]]): List[List[A]] = remaining match {
case Nil => groups
case _ => collectDistinct(remaining) match {
case (next, group) => distinctGroups(next, group :: groups)
}
}
// all second function with our input and an empty list of groups to begin with:
val result = distinctGroups(l, List())
在@TzachZohar的第一个答案中,分组后的另一种方法是从每个列表中提取一个元素,直到所有列表都为空:
val groups = l.groupBy(identity).values
Iterator
// continue removing the first element from every sublist, and discard empty tails
.iterate(groups)(_ collect { case _ :: (rest @ (_ :: _)) => rest } )
// stop when all sublists become empty and are removed
.takeWhile(_.nonEmpty)
// build and sort result lists
.map(_.map(_.head).toList.sorted)
.toList
考虑这种方法:
trait Proc {
def process(v:Int): Proc
}
case object Empty extends Proc {
override def process(v:Int) = Processor(v, Map(0 -> List(v)), 0)
}
case class Processor(prev:Int, map:Map[Int, List[Int]], lastTarget:Int) extends Proc {
override def process(v:Int) = {
val target = if (prev==v) lastTarget+1 else 0
Processor(v, map + (target -> (v::map.getOrElse(target, Nil))), target)
}
}
list.sorted.foldLeft[Proc](Empty) {
case (acc, item) => acc.process(item)
}
这里我们有一个简单的状态机。我们迭代初始状态为“空”的排序列表。一旦“空”处理项目,它将生成下一个状态“处理器”。
处理器在“prev”中具有以前的值,并且已分组项目的累积映射。它还有lastTarget—上次写入发生的列表的索引。
“Processor”所做的唯一一件事是计算当前处理项的目标:如果它与上一个相同,它将采用下一个索引,否则它将从索引0开始
val groups = l.groupBy(identity).values
Iterator
// continue removing the first element from every sublist, and discard empty tails
.iterate(groups)(_ collect { case _ :: (rest @ (_ :: _)) => rest } )
// stop when all sublists become empty and are removed
.takeWhile(_.nonEmpty)
// build and sort result lists
.map(_.map(_.head).toList.sorted)
.toList
trait Proc {
def process(v:Int): Proc
}
case object Empty extends Proc {
override def process(v:Int) = Processor(v, Map(0 -> List(v)), 0)
}
case class Processor(prev:Int, map:Map[Int, List[Int]], lastTarget:Int) extends Proc {
override def process(v:Int) = {
val target = if (prev==v) lastTarget+1 else 0
Processor(v, map + (target -> (v::map.getOrElse(target, Nil))), target)
}
}
list.sorted.foldLeft[Proc](Empty) {
case (acc, item) => acc.process(item)
}