如何在scala中按周拆分列表

时间:2014-07-24 02:59:50

标签: list scala split

case class Test(dayOfWeek:Int,b:Int=Random.nextInt)
val data=(3 to 100).map(_ % 7).map(Test(_))

如何将数据拆分成组,每组有一周的数据,如果一周没有完成,也有一个组。所以小组应该是

Group 1: (3,4,5,6)   // the number here is the dayOfWeek
Group 2: (0,1,2,3,4,5,6)
Group 3: (0,1,2,3,4,5,6)
...
last Group:(0,1,2)

3 个答案:

答案 0 :(得分:4)

Scala的集合非常强大,这应该分几行:

val (firstWeek, nextWeeks) = data.span(_.dayOfWeek != 0)
val weeks = (firstWeek :: nextWeeks.grouped(7).toList).dropWhile(_.isEmpty)

查看spangrouped here的文档。

println(weeks.zipWithIndex.map {
  case (week, i) => s"Group $i: (${week.map(_.dayOfWeek).mkString(",")})"
}.mkString("\n"))

输出:

Group 0: (3,4,5,6)
Group 1: (0,1,2,3,4,5,6)
Group 2: (0,1,2,3,4,5,6)
[snip]
Group 12: (0,1,2,3,4,5,6)
Group 13: (0,1,2,3,4,5,6)
Group 14: (0,1,2)

答案 1 :(得分:2)

你可以用折叠来做到这一点:

case class Test(dayOfWeek: Int, b: Int = scala.util.Random.nextInt)
val data = (3 to 100).map(_ % 7).map(Test(_))

val spans =
  data.foldLeft(Vector(Vector.empty[Test])) {
    case (zs :+ z, e) =>
      if (e.dayOfWeek == 0)
        if (z.nonEmpty)
          (zs :+ z) :+ Vector(e)
        else
          zs :+ Vector(e)
      else
        zs :+ (z :+ e)
  }

for ((g, i) <- spans.zipWithIndex) {
  println(f"Group $i: (${g.map(_.dayOfWeek).mkString(",")})")
}

输出:

Group 0: (3,4,5,6)
Group 1: (0,1,2,3,4,5,6)
Group 2: (0,1,2,3,4,5,6)
Group 3: (0,1,2,3,4,5,6)
Group 4: (0,1,2,3,4,5,6)
Group 5: (0,1,2,3,4,5,6)
Group 6: (0,1,2,3,4,5,6)
Group 7: (0,1,2,3,4,5,6)
Group 8: (0,1,2,3,4,5,6)
Group 9: (0,1,2,3,4,5,6)
Group 10: (0,1,2,3,4,5,6)
Group 11: (0,1,2,3,4,5,6)
Group 12: (0,1,2,3,4,5,6)
Group 13: (0,1,2,3,4,5,6)
Group 14: (0,1,2)

答案 2 :(得分:2)

这是一个适用于一般序列的递归版本,现在需要一个weekDay函数。

def groupByWeek[T](s: Seq[T], maxDay: Int = 6, weekDay: T => Int) = {
  @scala.annotation.tailrec
  def recurse(r: Seq[T], results: Seq[Seq[T]]): Seq[Seq[T]] =
    r.splitAt(r.indexWhere(item => weekDay(item) == maxDay)) match {
      case (hd, tl) if (hd.isEmpty && tl.isEmpty) => results
      case (hd, tl) if (hd.isEmpty) => results :+ tl
      case (hd, tl) => recurse(tl.tail, results :+ (hd :+ tl.head))
    }
  recurse(s,Seq.empty)
  }
}

这样称呼:

val weeks = groupByWeek(data, weekDay = (x:Test) => x.dayOfWeek)

你可以看到小组:

println(weeks.zipWithIndex.map {
  case (week, i) => s"Group $i: (${week.map(_.dayOfWeek).mkString(",")})"
}.mkString("\n"))

哪个输出:

Group 0: (3,4,5,6)
Group 1: (0,1,2,3,4,5,6)
Group 2: (0,1,2,3,4,5,6)
[snip]
Group 12: (0,1,2,3,4,5,6)
Group 13: (0,1,2,3,4,5,6)
Group 14: (0,1,2)