Scala 在列表中的位置插入

Scala 在列表中的位置插入,scala,Scala,此插入函数取自: 我想在列表的每一个元素处插入一个元素,因此我使用: val sl = List("1", "2", "3", "4", "5") //> sl : List[String] = List(1, 2, 3, 4, 5) insertAt("'a", 2, insertAt("'a", 4, sl)) //> res0: List[String] = List(1, 2, 'a, 3, 4, 'a, 5) 这是一个非常基本的实

此插入函数取自:

我想在列表的每一个元素处插入一个元素,因此我使用:

 val sl = List("1", "2", "3", "4", "5")          //> sl  : List[String] = List(1, 2, 3, 4, 5)
  insertAt("'a", 2, insertAt("'a", 4, sl))        //> res0: List[String] = List(1, 2, 'a, 3, 4, 'a, 5)
这是一个非常基本的实现,我想使用一个函数构造。我想我需要
要使用折页,请将列表分组为大小为2的列表,然后将这些列表合并为以分隔符分隔的列表:

  val sl = List("1","2","3","4","5")              //> sl  : List[String] = List(1, 2, 3, 4, 5)
  val grouped = sl grouped(2) toList              //> grouped  : List[List[String]] = List(List(1, 2), List(3, 4), List(5))
  val separatedList = grouped flatMap (_ :+ "a")  //> separatedList  : <error> = List(1, 2, a, 3, 4, a, 5, a)
val sl=List(“1”、“2”、“3”、“4”、“5”)/>sl:List[String]=List(1、2、3、4、5)
val grouped=sl grouped(2)toList/>grouped:List[List[String]=List(List(1,2)、List(3,4)、List(5))
val separatedList=分组平面图(:+“a”)/>separatedList:=列表(1,2,a,3,4,a,5,a)
编辑 刚才看到我的解决方案有一个不在问题中的尾随标记。要消除此问题,请执行长度检查:

  val separatedList2 = grouped flatMap (l => if(l.length == 2) l :+ "a" else l)
                        //> separatedList2  : <error> = List(1, 2, a, 3, 4, a, 5)
val separatedList2=分组平面图(l=>if(l.length==2)l:+a else l)
//>separatedList2:=列表(1,2,a,3,4,a,5)

您也可以使用滑动:

val sl = List("1", "2", "3", "4", "5")   

def insertEvery(n:Int, el:String, sl:List[String]) =
   sl.sliding(2, 2).foldRight(List.empty[String])( (xs, acc) => if(xs.length == n)xs:::el::acc else xs:::acc)

insertEvery(2,"x",sl) // res1: List[String] = List(1, 2, x, 3, 4, x, 5)

忘记插入,使用纯折叠:

def insertAtEvery[A](e: A, n: Int, ls: List[A]): List[A] = 
  ls.foldLeft[(Int, List[A])]((0, List.empty)) {
    case ((pos, result), elem) =>
      ((pos + 1) % n, if (pos == n - 1) e :: elem :: result else elem :: result)
  }._2.reverse

递归和模式匹配是函数结构。通过模式匹配在
splitAt
的输出上插入新的
elem
,然后与剩余的输入一起递归。看起来更容易阅读,但我不满意这一个的类型签名

def insertEvery(xs: List[Any], n: Int, elem: String):List[Any] = xs.splitAt(n) match {
  case (xs, List()) => if(xs.size >= n) xs ++ elem else xs
  case (xs, ys) => xs ++ elem ++ insertEvery(ys, n, elem)
}
样本运行

scala> val xs = List("1","2","3","4","5")
xs: List[String] = List(1, 2, 3, 4, 5)

scala> insertEvery(xs, 1, "a")
res1: List[Any] = List(1, a, 2, a, 3, a, 4, a, 5, a)

scala> insertEvery(xs, 2, "a")
res2: List[Any] = List(1, 2, a, 3, 4, a, 5)

scala> insertEvery(xs, 3, "a")
res3: List[Any] = List(1, 2, 3, a, 4, 5)

使用递归的实现:

注意
n
必须小于
列表的
大小
,否则将引发
异常

scala> def insertAt[A](e: A, n: Int, ls: List[A]): List[A] = n match {
     |   case 0 => e :: ls
     |   case _ => ls.head :: insertAt(e, n-1, ls.tail)
     | }
insertAt: [A](e: A, n: Int, ls: List[A])List[A]


scala> insertAt("'a", 2, List("1", "2", "3", "4"))
res0: List[String] = List(1, 2, 'a, 3, 4)

考虑使用
zipWithIndex
索引列表位置,依此类推

sl.zipWithIndex.flatMap { case(v,i) => if (i % 2 == 0) List(v) else List(v,"a") }

我们在这里生成了多少中间列表?N/2?听起来很慢。
sl.zipWithIndex.flatMap { case(v,i) => if (i % 2 == 0) List(v) else List(v,"a") }