0
import java.time.LocalDate

case class Day(date: LocalDate, other: String)

val list = Seq(
  Day(LocalDate.of(2016, 2, 1), "text"),
  Day(LocalDate.of(2016, 2, 2), "text"),  // Tuesday
  Day(LocalDate.of(2016, 2, 3), "text"),
  Day(LocalDate.of(2016, 2, 4), "text"),
  Day(LocalDate.of(2016, 2, 5), "text"),
  Day(LocalDate.of(2016, 2, 6), "text"),
  Day(LocalDate.of(2016, 2, 7), "text"),
  Day(LocalDate.of(2016, 2, 8), "text"),
  Day(LocalDate.of(2016, 2, 9), "text"),
  Day(LocalDate.of(2016, 2, 10), "text"),
  Day(LocalDate.of(2016, 2, 11), "text"),
  Day(LocalDate.of(2016, 2, 12), "text"),
  Day(LocalDate.of(2016, 2, 13), "text"),
  Day(LocalDate.of(2016, 2, 14), "text"),
  Day(LocalDate.of(2016, 2, 15), "text"),
  Day(LocalDate.of(2016, 2, 16), "text"),
  Day(LocalDate.of(2016, 2, 17), "text")
)

// hard code, for example Tuesday
def groupDaysBy(list: Seq[Day]): List[List[Day]] = {
  ???
}

val result =
Seq(
  Seq(Day(LocalDate.of(2016, 2, 1), "text")),  // Separate
  Seq(Day(LocalDate.of(2016, 2, 2), "text"),  // Tuesday
    Day(LocalDate.of(2016, 2, 3), "text"),
    Day(LocalDate.of(2016, 2, 4), "text"),
    Day(LocalDate.of(2016, 2, 5), "text"),
    Day(LocalDate.of(2016, 2, 6), "text"),
    Day(LocalDate.of(2016, 2, 7), "text"),
    Day(LocalDate.of(2016, 2, 8), "text")),
  Seq(Day(LocalDate.of(2016, 2, 9), "text"),  // Tuesday
    Day(LocalDate.of(2016, 2, 10), "text"),
    Day(LocalDate.of(2016, 2, 11), "text"),
    Day(LocalDate.of(2016, 2, 12), "text"),
    Day(LocalDate.of(2016, 2, 13), "text"),
    Day(LocalDate.of(2016, 2, 14), "text"),
    Day(LocalDate.of(2016, 2, 15), "text")),
  Seq(Day(LocalDate.of(2016, 2, 16), "text"), // Tuesday
    Day(LocalDate.of(2016, 2, 17), "text"))
)

assert(groupDaysBy(list) == result)

I have a list of Day object, and I want to group every 7 days together and the start date can be any day (from Monday to Sunday, I give Tuesday as an example).

Above is the function and expected result for my requirement. I am wondering how can I take advantage of Scala collection API to achieve without tail recursive?

ttt
  • 3,934
  • 8
  • 46
  • 85
  • Why do you want to work without tail recursion? That's what makes Scala fast. – bash0r Feb 04 '16 at 10:07
  • `groupBy` http://www.scala-lang.org/api/current/index.html#scala.collection.Seq@groupBy[K](f:A=>K):scala.collection.immutable.Map[K,Repr] should be most of what you need – The Archetypal Paul Feb 04 '16 at 10:21

2 Answers2

1

Here's what you can do:

// hard code, for example Tuesday
def groupDaysBy(list: Seq[Day]): Seq[Seq[Day]] = {
  val (list1,list2)= list.span(_.date.getDayOfWeek != DayOfWeek.TUESDAY)
  Seq(list1) ++ list2.grouped(7)
}

I would recommend taking day as a parameter instead of hardcoding though, so it becomes

// hard code, for example Tuesday
def groupDaysBy(list: Seq[Day], dayOfWeek: DayOfWeek): Seq[Seq[Day]] = {
  val (list1,list2)= list.span(_.date.getDayOfWeek != dayOfWeek)
  Seq(list1) ++ list2.grouped(7)
}

...

assert(groupDaysBy(list, DayOfWeek.TUESDAY) == result)
slouc
  • 9,508
  • 3
  • 16
  • 41
  • I also changed the signature of `groupDaysBy` so that it returns a `Seq[Seq[Day]]` because that's what you said you expected as the result. – slouc Feb 04 '16 at 11:02
  • Thanks for your solution. That's really what I want. BTW, one question is how about if the date is not continuous? For example, some whole week (from Monday to Sunday) is missing in the Days list. Thanks – ttt Feb 04 '16 at 11:08
  • If the sequence is not continuous, then you (obviously) cannot group it in chunks of seven. In that case you would have to resort to `groupBy` instead. You would need to get the weekOfTheMonth for each date and then group by that. See [this](http://stackoverflow.com/questions/26012434/get-week-number-of-localdate-java-8) on how to get the week for each date. Solution I provided up there doesn't depend on any externals (e.g. doesn't care if weeks in the `Locale` for your country begin with Sunday), but if you have "holes" in your sequence than you have to use this approach. – slouc Feb 04 '16 at 11:15
0

Map your list to create a Tuple(GroupKey, value) with GroupKey a value representing a uniq week (year*53 + week_of_the_year) for example. Then you can group on GroupKey

Benjamin
  • 3,350
  • 4
  • 24
  • 49