将值插入MutableList

时间:2016-09-12 14:50:00

标签: scala

我想在scala MutableList中的特定索引中插入一个值,它会将连续元素推送到一个索引(很像java.util.List.add(index, element)方法)。我尝试使用MutableList.add()方法并编译但令人讨厌的是我在运行时遇到了UnsupportedOperation异常。

我编写了以下方法(其中mListMutableList[String]实例)但是你可以看到它需要很多我认为不必要的转换步骤。是否有内置/更快的方式?

def insert(idx: Int, element: String): Unit ={
    val newList = new scala.collection.mutable.MutableList[String]()
    for(i <- 0 until idx) newList += mList(i)
    newList += element
    for(i <- idx until content.size) newList += mList(i)
    mList = newList
}

Psuedocode示例:

mList = ["a", "f", "x", "e"]
insert(2, "z")
// mList is now ["a", "f", "z", "x", "e"]

我在这里看到的答案适用于不可变列表,但没有一个适用于可变列表。

3 个答案:

答案 0 :(得分:4)

以下是在可变列表中插入元素的另一种方法:

val ls = MutableList(1,2,3,4) 

val pair = ls.splitAt(1) // split it at the appropriate index into two lists.

pair._1 ++ MutableList(20) ++ pair._2 // MutableList(1, 20, 2, 3, 4)

答案 1 :(得分:2)

另一种方法是使用可变的ListBuffer并且具有恒定时间附加和前置操作。转换为不可变列表只是lb.toList的一种情况。

答案 2 :(得分:1)

这是使用patch方法将指定索引处的当前元素替换为包含新元素后跟当前元素的序列的另一种方法:

ls.patch(index, Seq(value, self(index)), 1)

我发现将其转换为可重用的解决方案非常困难,因为patch方法采用隐式参数来构建正确的集合类型,并且可变和不可变序列的构建器具有不同的类型签名。这就是我到目前为止所做的:

// --- insert(index, value) implementation.
// uses a RichSeq wrapper to decorate mutable and immutable sequences/lists with the insert(...) method.

import scala.collection.generic.CanBuildFrom
import scala.collection.immutable.List
import scala.collection.immutable.List._
import scala.collection.{GenSeqLike, mutable}

object RichSeq {
  type MutableSeqType[A, +Repr] = GenSeqLike[A, Repr] with mutable.Builder[A, Repr]
  type ImmutableSeqType[+A, +Repr] = GenSeqLike[A, Repr]

  def apply[A, Repr](self: MutableSeqType[A, Repr]): RichMutableSeq[A, Repr] = new RichMutableSeq[A, Repr](self)
  def apply[A, Repr, Coll](self: ImmutableSeqType[A, Repr]): RichImmutableSeq[A, Repr] = new RichImmutableSeq[A, Repr](self)

  implicit def toRichSeq[A, Repr](self: MutableSeqType[A, Repr]): RichMutableSeq[A, Repr] = RichSeq(self)
  implicit def toRichSeq[A, Repr](self: ImmutableSeqType[A, Repr]): RichImmutableSeq[A, Repr] = RichSeq(self)
}

final class RichMutableSeq[A, Repr](val self: RichSeq.MutableSeqType[A, Repr]) {
  import RichSeq._
  def insert(index: Int, value: A)(implicit ev: CanBuildFrom[Repr, A, MutableSeqType[A, Repr]]): MutableSeqType[A, Repr] = self.patch(index, Seq(value, self(index)), 1)(ev)
}

final class RichImmutableSeq[A, Repr](val self: RichSeq.ImmutableSeqType[A, Repr]) {
  import RichSeq._
  def insert(index: Int, value: A)(implicit ev: CanBuildFrom[Repr, A, ImmutableSeqType[A, Repr]]): ImmutableSeqType[A, Repr] = self.patch(index, Seq(value, self(index)), 1)(ev)
}

// --- test object ---

object TestRichSeq {
  def main(args: Array[String]): Unit = {
    import RichSeq._

    val ls0 = mutable.MutableList(1, 2, 3, 4)
    val ls1 = ls0.insert(1, 20)

    println(ls1)

    val ls2 = List(1, 2, 3, 4)
    val ls3 = ls2.insert(1, 20)

    println(ls3)
  }
}

重用Samar的测试,测试程序的输出是:

MutableList(1, 20, 2, 3, 4)
List(1, 20, 2, 3, 4)

该解决方案适用于可变列表和不可变列表,但它似乎需要更多地使用含义而不是我想要的。