Aamir
Aamir

Reputation: 2422

Convert for loop to functional style

I have a requirement where in I have a list of OffsetDateTime and I have to compare each item in list to every other item and this applies to each item in list, and finally get a list of Boolean,I tried with recursion and foldLeft but it didn't work out, finally I ended up with for loop and mutable ListBuffer, I got my solution but code isn't functional style, here is my code:

val sd1 = OffsetDateTime.of(LocalDateTime.of(2017, 4, 14, 6, 30, 22),
ZoneOffset.ofHoursMinutes(5, 30))

val ed1 = OffsetDateTime.of(LocalDateTime.of(2017, 4, 14, 9, 30, 20),
ZoneOffset.ofHoursMinutes(5, 30))

 val sd2 = OffsetDateTime.of(LocalDateTime.of(2017, 4, 14, 10, 30, 22),
  ZoneOffset.ofHoursMinutes(5, 30))

val ed2 = OffsetDateTime.of(LocalDateTime.of(2017, 4, 14, 11, 30, 22),
   ZoneOffset.ofHoursMinutes(5, 30))

val sd3 = OffsetDateTime.of(LocalDateTime.of(2017, 4, 15, 7, 30, 22),
   ZoneOffset.ofHoursMinutes(5, 30))

val ed3 = OffsetDateTime.of(LocalDateTime.of(2017, 4, 15, 9, 30, 22),
  ZoneOffset.ofHoursMinutes(5, 30))


case class DT(st: OffsetDateTime, et: OffsetDateTime)

val x1 = DT(sd1, ed1)
val x2 = DT(sd2, ed2)
val x3 = DT(sd3, ed3)
val l: List[DT] = List(x1, x2, x3)

here below is the solution with for loop,can somebody please help with how to convert below piece of code to functional style.Thanks in advance.

var lb = ListBuffer[Boolean]()
 for(i <- l.indices) {
  for(j <- i + 1 until l.size) {
    val res = overlapping(l(i).st,l(i).et,l(j).st,l(j).et)
    lb.append(res)
  }
}

Upvotes: 1

Views: 168

Answers (3)

Kolmar
Kolmar

Reputation: 14224

You can do it with a call to l.combinations(2) method. It gives an iterator over all possible pairs of elements:

scala> List(1,2,3).combinations(2) foreach println
List(1, 2)
List(1, 3)
List(2, 3)

So the code to solve your problem looks like this:

l.combinations(2).map {
  case List(DT(st1, et1), DT(st2, et2)) => 
    overlapping(st1, et1, st2, et2)
}.toList

You can achieve a similar effect with l.tails, which returns an iterator over all the suffixes of the list:

l.tails.flatMap {
  case DT(st1, et1) :: tail => tail.map {
    case DT(st2, et2) => overlapping(st1, et1, st2, et2)
  }
  case _ => Nil
}.toList

Also, accessing a list by index, e.g. l(i), has very poor performance, and you should try to avoid using it.

Upvotes: 0

Puneeth Reddy V
Puneeth Reddy V

Reputation: 1578

If you are purpose is to get the current and next element in a iteration of a list you can use slide for this purpose. For example

scala> val myList = List(1,2,3,4,5)
myList: List[Int] = List(1, 2, 3, 4, 5)

scala> myList.sliding(2).foreach(print)
//List(1, 2)List(2, 3)List(3, 4)List(4, 5)

Upvotes: 0

ziggystar
ziggystar

Reputation: 28676

Your last "for-loop" translates nicely into a for-comprehension:

val lb = for{
  i <- l.indices
  j <- i + 1 until l.size
} yield overlapping(l(i).st,l(i).et,l(j).st,l(j).et)

Upvotes: 3

Related Questions