2012-06-21 8 views
5

私は、ランダムな位置でNoneList[Option[MyClass]]を持っていると私は秩序を維持し、List[MyClass]から、もう一度そのリストを「埋める」する必要があります。ここでどのように慣用のScalaを使用して別のリストから[オプション]の一覧で(塗りつぶし)なしエントリを交換するには?

はサンプルリストと期待された結果、次のとおりです。だから、

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のでしょうか?

答えて

13
def fillL[T](a:List[Option[T]], b:List[T]) = { 
    val iterB = b.iterator 
    a.map(_.orElse(Some(iterB.next))) 
} 
1

イテレータソリューションは、間違いなく慣用スカラ座で、そして間違いなく、簡潔で理解しやすいですが、それはあなたが副作用の地にしっかりとしているイテレータにnextを呼び出す機能 -any時間ではありません。

より機能的なアプローチは、折り目を使用するために、次のようになります。ここでは

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つのその他のリスト維持しながら、私たちがgappyのリスト内を移動:残りのために私たちが処理した項目に1つ、およびその他のフィラー要素。

この種のソリューションは、必ずしも他の-Scalaはあなたがその中で機能的で不可欠な構成を混在できるように設計されている方法、それは潜在的な利点を持っているよりも良いではありません。

+0

「あなたは副作用の地にしっかりとしているイテレータの次の呼び出しの任意の時間。」確かに、この場合には、それらをきちんと参照透明のままの方法でencapuslatedています。 –

+0

@Paul:そうですね、もう一つの解決策は素晴らしいと思います。私は自分のコードでこの問題を解決する方法を選択しています。しかし、それは副作用を伴い、いくつかの同様の状況では理想的ではないかもしれません。 –

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

おそらくあなたがそれを埋めるために、物事を使い果たしたら、あなただけのままにそこにNone秒の残りの部分。

関連する問題