2016-05-07 30 views
3

たとえば、List[(Int, Int, Foo)]など、ある値に関連付けられた範囲のリストがあるとします。範囲は互いに素であることが保証されているため、重複することはありません。範囲は、指定された文字列の全範囲をカバーしません。文字列を(String, Option[Foo])のセクションに分割できるように、各文字列の一部にそれぞれFooを関連付ける必要があります。リストに欠損値を挿入する

私の考えでは、このList[(Int, Int, Foo)]List[(Int, Int, Option[Foo])]に変換して、欠落している範囲がすべて記入され、Noneと関連付けられるようにします。この新しいリストをマッピングして、各Fooを文字列の一部と関連付けることができます。私はfilledInValuesに、またはinputからresinputから取得する必要がありますどのよう

いくつかの具体的なコード

case class Foo(i: Int) 
val str = "a" * 99 // A random string of length 99 
val input = List((5, 10, Foo(1)), (56, 60, Foo(2)) 
// ??? 
val filledInValues = List(
    (0, 4, None), 
    (5, 10, Some(Foo(1))), 
    (11, 55, None), 
    (56, 60, Some(Foo(2))), 
    (61, 98, None) 
) 
val res = filledInValues map { case (start, end, f) => 
    (str.substring(start, end), f) 
} 

答えて

6

この1つは楽しかったです。

case class Foo(x:Int) 

val xs = List((5, 10, Foo(1)), (56, 60, Foo(2))) 
val str = "a" * 99 // A random string of length 99 

// change the Foo to Option[Foo]. We do this now so we can use None 
// in the sentinels we're about to add. 

val ys = xs.map{case(a,b,c) => (a, b, Option(c))} 

// Add dummy/sentinel elements to start and end 
val zs = (-1, -1, None:Option[Foo])::(ys:+ ((str.length, str.length, None:Option[Foo]))) 

// Now take each pair and if there's a gap, use the first, then a (n, m, None) element 
// if no gap, just the first of the pair 
zs.sliding(2).flatMap{ 
    case List(a,b) => 
    if (a._2+1 != b._1) 
     List(a, (a._2 + 1, b._1 -1, None:Option[Foo])) 
    else 
     List(a) 
    }.toList.tail 
// and drop the dummy element from the beginning 
// Note because we never return the second of the pair, the end sentinel 
// value gets discarded automatically 

//> res0:= List((0,4,None), 
       (5,10,Some(Foo(1))), 
       (11,55,None), 
       (56,60,Some(Foo(2))), 
       (61,98,None)) 
0
def ranges(str: String, ls: List[(Int, Int, Foo)]): List[(Int, Int, Option[Foo])] = { 
    val length = str.length 
    def loop(i: Int, ls: List[(Int, Int, Foo)], acc: List[(Int, Int, Option[Foo])]): List[(Int, Int, Option[Foo])] = { 
    ls match { 
     case Nil if i < length => (i, length -1, None) :: acc 
     case Nil => acc 
     case (start, end, _) :: lss if start > i => loop(start, ls, (i, start - 1, None) :: acc) 
     case (start, end, f) :: lss if start == i => loop(end + 1, lss, (start, end, Some(f)) :: acc) 
     case _ => throw new IllegalStateException 
    } 
    } 
    loop(0, ls, Nil).reverse 
} 

テストそれ:

scala> ranges(str, input) 
res0: List[(Int, Int, Option[Foo])] = List((0,4,None), (5,10,Some(Foo(1))), (11,55,None), (56,60,Some(Foo(2))), (61,98,None)) 
関連する問題