我怎样才能在scala中交错2个列表的元素

mar*_*cin 6 scala scalaz

我想组合两个任意长度的列表,使得第二个列表中的元素在每个第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完成相同的逻辑?

谢谢大家的回答.他们都对我很有帮助!

Yo *_*ght 7

认识我的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不同.坏消息是交错不再是尾递归


Rok*_*alj 5

这变得非常简单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)