假设我们有一个与某个值相关的范围列表,比如a List[(Int, Int, Foo)].保证范围是不相交的,因此永远不会重叠.范围不包括给定字符串的整个范围.我想将每个Foo字符串与字符串的某些部分相关联,以便字符串可以拆分为(String, Option[Foo]).
我的想法是将其转换List[(Int, Int, Foo)]为List[(Int, Int, Option[Foo])]每个缺失的范围都填写并与无关联.然后可以映射此新列表以将每个列表Foo与字符串的某些部分相关联.
一些具体的代码
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)
}
Run Code Online (Sandbox Code Playgroud)
我应该如何从获取input到filledInValues,或input到res?
这个很有趣.
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))
Run Code Online (Sandbox Code Playgroud)