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") }