2014-07-24 15 views
4
case class Test(dayOfWeek:Int,b:Int=Random.nextInt) 
val data=(3 to 100).map(_ % 7).map(Test(_)) 

如何將數據拆分成組,每個組有一個星期的數據,如果一個星期沒有完成,也有一個組。因此,組應該是如何在scala中按星期劃分一個列表

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) 

回答

4

Scala的集合是真的很強大,這應該做幾行:

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

看看這個文檔的spangroupedhere

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) 
+0

是的,這是我尋找的優雅! –

+0

@如果其中一個答案滿足你,考慮接受它(http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work)。 – Utaal

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) 
+0

我認爲,如果第一個元素是0,你會在一開始就空組結束了。例如,'val data =(0到10).map(_%7).map(Test(_))' –

+0

@將更新。 – dhg

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)