插入列表中的位置

时间:2014-05-12 20:29:01

标签: scala

此插入功能取自:

http://aperiodic.net/phil/scala/s-99/p21.scala

  def insertAt[A](e: A, n: Int, ls: List[A]): List[A] = ls.splitAt(n) match {
    case (pre, post) => pre ::: e :: post
  }

我想在List的每个第二个元素处插入一个元素,所以我使用:

 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)

这是一个非常基本的实现,我想使用其中一个功能结构。我想我需要 使用foldLeft?

6 个答案:

答案 0 :(得分:1)

将列表分组为大小为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 separatedList2 = grouped flatMap (l => if(l.length == 2) l :+ "a" else l)
                        //> separatedList2  : <error> = List(1, 2, a, 3, 4, a, 5)

答案 1 :(得分:0)

你也可以使用滑动:

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)

答案 2 :(得分:0)

忘记insertAt,使用纯foldLeft:

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

答案 3 :(得分:0)

递归和模式匹配是功能构造。在elem的输出上通过模式匹配插入新的splitAt,然后使用剩余的输入进行递归。似乎更容易阅读,但我对这个类型的签名不满意。

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)

答案 4 :(得分:0)

使用递归的实现:

注意 n必须小于size的{​​{1}},否则会引发List

Exception

答案 5 :(得分:0)

考虑使用zipWithIndex索引列表位置,等等

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