How to replace (fill in) No entries in the parameter list from another list using the idiomatic Scala?

I have List[Option[MyClass]]s Nonein random positions, and I need to "fill" this list again, from List[MyClass], maintaining order.

The following are examples of lists and expected results:

val listA = List(Some(3),None,Some(5),None,None)
val listB = List(7,8,9)
val expectedList = List(Some(3), Some(7), Some(5), Some(8), Some(9))

So, what will the idiomatic Scala look like to handle this list?

+5
source share
3 answers
def fillL[T](a:List[Option[T]], b:List[T]) = {
    val iterB = b.iterator
    a.map(_.orElse(Some(iterB.next)))
}
+13
source

The iterator solution may be the idiom of Scala, and it is clearly concise and understandable, but it is not functional - at any time when you call nexton the iterator, you are firmly in the country of side effects.

:

def fillGaps[A](gappy: List[Option[A]], filler: List[A]) =
  gappy.foldLeft((List.empty[Option[A]], filler)) {
    case ((current, fs), Some(item)) => (current :+ Some(item), fs)
    case ((current, f :: fs), None) => (current :+ Some(f), fs)
    case ((current, Nil), None) => (current :+ None, Nil)
  }._1

gappy, : , .

, - Scala , , .

+1

I would simply write it straightforwardly, matching the heads of the lists and appropriately handling each case:

def fill[A](l1: List[Option[A]], l2: List[A]) = (l1, l2) match {
  case (Nil, _) => Nil
  case (_, Nil) => l1
  case (Some(x) :: xs, _) => Some(x) :: fill(xs, l2)
  case (None :: xs, y :: ys) => Some(y) :: fill(xs, ys)
}

Presumably, once you have exhausted everything to fill it, you simply leave the rest there None.

0
source

All Articles