5

ランダムな位置にList[Option[MyClass]]withがあり、順序を維持しながらNone、からそのリストを再度「入力」する必要があります。List[MyClass]

サンプルリストと期待される結果は次のとおりです。

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

では、そのリストを処理するための慣用的なScalaはどのようになりますか?

4

3 に答える 3

13
def fillL[T](a:List[Option[T]], b:List[T]) = {
    val iterB = b.iterator
    a.map(_.orElse(Some(iterB.next)))
}
于 2012-06-21T13:45:32.697 に答える
1

イテレータソリューションは間違いなく慣用的なScalaであり、間違いなく簡潔で理解しやすいものですが、機能的ではありません。イテレータを呼び出すときはいつでもnext、副作用の領域にしっかりといることになります。

より機能的なアプローチは、フォールドを使用することです。

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

ここでは、他の2つのリストを維持しながらギャップのあるリストを移動します。1つは処理したアイテム用で、もう1つは残りのフィラー要素用です。

この種のソリューションは必ずしも他のソリューションよりも優れているわけではありません。Scalaは、機能的な構造と命令型の構造をそのように組み合わせることができるように設計されていますが、潜在的な利点があります。

于 2012-06-21T16:12:45.887 に答える
0

リストの先頭を照合し、各ケースを適切に処理して、簡単な方法で記述します。

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)
}

おそらく、それを埋めるために物がなくなったら、残りのNonesをそこに残すだけです。

于 2012-06-21T21:02:41.960 に答える