Scala:在列表的指定位置插入新元素

Hee*_*eeL 10 scala

没有内置函数或List方法允许用户在List的特定位置添加新元素.我已经写了一个函数,但是我不确定这样做是个好主意,即使它运行得很好:

def insert(list: List[Any], i: Int, value: Any) = {
  list.take(i) ++ List(value) ++ list.drop(i)
}
Run Code Online (Sandbox Code Playgroud)

用法:

scala> insert(List(1,2,3,5), 3, 4)
res62: List[Any] = List(1, 2, 3, 4, 5)
Run Code Online (Sandbox Code Playgroud)

Jör*_*tag 36

类型安全

我看到的最明显的是缺乏类型安全/丢失类型信息.我会在列表的元素类型中使方法通用:

def insert[T](list: List[T], i: Int, value: T) = {
  list.take(i) ++ List(value) ++ list.drop(i)
}
Run Code Online (Sandbox Code Playgroud)

样式

如果正文只包含一个表达式,则不需要花括号:

def insert[T](list: List[T], i: Int, value: T) = 
  list.take(i) ++ List(value) ++ list.drop(i)
Run Code Online (Sandbox Code Playgroud)

效率

@Marth关于使用List.splitAt避免两次遍历列表的评论也很好:

def insert[T](list: List[T], i: Int, value: T) = {
  val (front, back) = list.splitAt(i)
  front ++ List(value) ++ back
}
Run Code Online (Sandbox Code Playgroud)

接口

能够一次插入多个值可能很方便:

def insert[T](list: List[T], i: Int, values: T*) = {
  val (front, back) = list.splitAt(i)
  front ++ values ++ back
}
Run Code Online (Sandbox Code Playgroud)

接口,取2

你可以使这个扩展方法List:

implicit class ListWithInsert[T](val list: List[T]) extends AnyVal {
  def insert(i: Int, values: T*) = {
    val (front, back) = list.splitAt(i)
    front ++ values ++ back
  }
}

List(1, 2, 3, 6).insert(3, 4, 5)
// => List(1, 2, 3, 4, 5, 6)
Run Code Online (Sandbox Code Playgroud)

闭幕致辞

但请注意,插入列表中间并不适合使用缺点列表.你可以用(可变的)链表或动态数组来改善.


Ben*_*ich 25

你也可以使用xs.patch(i, ys, r),通过使用和制作单例来替换补丁开头的r元素:xsiysr=0ys

List(1, 2, 3, 5).patch(3, List(4), 0)
Run Code Online (Sandbox Code Playgroud)


ser*_*inc 5

马丁·奥德斯基 (Martin Odersky) 本人的 Scala 课程中,他的实现类似于

def insert(list: List[Any], i: Int, value: Any): List[Any] = list match {
  case head :: tail if i > 0 => head :: insert(tail, i-1, value)
  case _ => value :: list
}
Run Code Online (Sandbox Code Playgroud)

最多遍历一次。