2014-07-24 2 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) 

Посмотрите на документ для span и groupedhere.

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

@Will, обновлено. – 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) 
Смежные вопросы