我想组合两个任意长度的列表,使得第二个列表中的元素在每个第n个元素之后插入到第一个列表中.如果第一个列表长度小于n,则不会产生插入.
所以有
val a = List(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
val b = List(101,102,103)
val n = 3
Run Code Online (Sandbox Code Playgroud)
我希望结果列表看起来像这样:
List(1,2,3,101,4,5,6,102,7,8,9,103,10,11,12,13,14,15)
Run Code Online (Sandbox Code Playgroud)
我有这个使用foldLefton a,但我想知道如何使用Scalaz完成相同的逻辑?
谢谢大家的回答.他们都对我很有帮助!
认识我的apomorphism朋友
def apo[A, B](v: B)(f: B => Option[(A, Either[B, List[A]])]): List[A] = f(v) match {
case None => Nil
case Some((a, Left(b))) => a :: apo(b)(f)
case Some((a, Right(as))) => a :: as
}
Run Code Online (Sandbox Code Playgroud)
您的交错方法可以像这样实现
def interleave[A](period: Int, substitutes: List[A], elems: List[A]): List[A] =
apo((period, substitutes, elems)){
case (_, _, Nil) => None
case (_, Nil, v :: vs) => Some((v, Right(vs)))
case (0, x :: xs, vs) => Some((x, Left((period, xs, vs))))
case (n, xs, v :: vs) => Some((v, Left((n - 1, xs, vs))))
}
Run Code Online (Sandbox Code Playgroud)
这给出了:
scala> interleave(3, b, a)
res1: List[Int] = List(1, 2, 3, 101, 4, 5, 6, 102, 7, 8, 9, 103 , 10, 11 , 12, 13, 14, 15)
Run Code Online (Sandbox Code Playgroud)
好处是,当a或b为Nil时计算结束,与foldLeft不同.坏消息是交错不再是尾递归
这变得非常简单zipAll。此外,您可以选择第二个数组的元素数量(在本例中为 1):
val middle = b.grouped(1).toList
val res = a.grouped(n).toList.zipAll(middle, Nil, Nil)
res.filterNot(_._1.isEmpty).flatMap(x => x._1 ++ x._2)
Run Code Online (Sandbox Code Playgroud)
或者,如果你愿意的话,一句:
a.grouped(n).toList.zipAll(b.map(List(_)), Nil, Nil).filterNot(_._1.isEmpty).flatMap(x => x._1 ++ x._2)
Run Code Online (Sandbox Code Playgroud)
您还可以创建一个隐式类,这样您就可以a.interleave(b, 3)使用可选的第三个参数来调用 or a.interleave(b, 3, 1)。
| 归档时间: |
|
| 查看次数: |
2686 次 |
| 最近记录: |