【发布时间】:2011-07-01 01:13:46
【问题描述】:
如何用不可变列表按索引替换元素。
例如
val list = 1 :: 2 ::3 :: 4 :: List()
list.replace(2, 5)
【问题讨论】:
如何用不可变列表按索引替换元素。
例如
val list = 1 :: 2 ::3 :: 4 :: List()
list.replace(2, 5)
【问题讨论】:
如果要替换索引2,那么
list.updated(2,5) // Gives 1 :: 2 :: 5 :: 4 :: Nil
如果你想找到所有有 2 的地方,然后把 5 放进去,
list.map { case 2 => 5; case x => x } // 1 :: 5 :: 3 :: 4 :: Nil
在这两种情况下,您并没有真正“替换”,而是返回了一个新列表,该列表在那个(那些)位置具有不同的元素。
【讨论】:
你可以使用list.updated(2,5)(这是Seq上的一个方法)。
为此目的使用scala.collection.immutable.Vector 可能会更好,因为Vector 的更新需要(我认为)恒定时间。
【讨论】:
Vector 上的updated 不依赖于索引,而List 上的updated 则为O(index)。这使得固定大小的集合的时间非常恒定,这很可能适用。我不否认你所说的,但我认为这是一个有趣的观点。
List 上的updated 是O(index) 和Vector 上的updated 是O(lg size) 是否正确,这可能使List 在以下情况下具有优势size 很大,但index 很小? (我很想知道在哪里可以找到有关 Scala 不可变结构的时间保证的更多信息。)
O((log size)/32)。实际上,它接受的最大嵌套层数是 6,每层有 32 个元素。因此,对于可能的最大集合,您必须复制 6 * 32 个元素。如果您确定只有前几个元素会被更新,那么更新List 可能会成功,但它很快就会开始失去任何优势。至于查找它,有 scala-lang.org/docu/files/collections-api/collections_40.html,但您也可以通过 Scaladoc 上的链接检查实现本身。
Vector具有良好的空间参考局部性,所以它是缓存友好的。另一方面,List 的引用位置很差。
除了前面说的,还可以使用patch函数来替换序列的子序列:
scala> val list = List(1, 2, 3, 4)
list: List[Int] = List(1, 2, 3, 4)
scala> list.patch(2, Seq(5), 1) // replaces one element of the initial sequence
res0: List[Int] = List(1, 2, 5, 4)
scala> list.patch(2, Seq(5), 2) // replaces two elements of the initial sequence
res1: List[Int] = List(1, 2, 5)
scala> list.patch(2, Seq(5), 0) // adds a new element
res2: List[Int] = List(1, 2, 5, 3, 4)
【讨论】:
如果你做了很多这样的替换,最好使用可变类或数组。
【讨论】:
您可以使用 map 生成一个新列表,如下所示:
@ list
res20: List[Int] = List(1, 2, 3, 4, 4, 5, 4)
@ list.map(e => if(e==4) 0 else e)
res21: List[Int] = List(1, 2, 3, 0, 0, 5, 0)
【讨论】:
也可以使用patch function as来实现
scala> var l = List(11,20,24,31,35)
l: List[Int] = List(11, 20, 24, 31, 35)
scala> l.patch(2,List(27),1)
res35: List[Int] = List(11, 20, 27, 31, 35)
其中 2 是我们要添加值的位置,List(27) 是我们要添加到列表中的值,1 是要从原始列表中替换的元素数。
【讨论】:
下面是一个简单的scala List中字符串替换的例子,你可以对其他类型的数据做类似的操作
scala> val original: List[String] = List("a","b")
original: List[String] = List(a, b)
scala> val replace = original.map(x => if(x.equals("a")) "c" else x)
replace: List[String] = List(c, b)
【讨论】:
cols 来自哪里?这个答案与 damon-lin 两年前的答案有何不同?