在scala中更新数组的切片

时间:2014-09-26 01:09:43

标签: arrays scala

Scala数组有一个slice()方法来返回一个连续的子集。这很有用!

scala> val arr = Array(1,2,3,4,5,6,7,8)
arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8)
scala> arr.slice(2,6)
res1: Array[Int] = Array(3, 4, 5, 6)

现在如何更新连续的子集?我们有什么简洁的选择 - 即可能比我们使用System.arrarycopy的后备更好?

scala> val carr = Array(111,222,333,444,555,666,777,888)
carr: Array[Int] = Array(111, 222, 333, 444, 555, 666, 777, 888)

scala> System.arraycopy(carr,3,arr,3,5)

scala> arr
res6: Array[Int] = Array(1, 2, 3, 444, 555, 666, 777, 888)

3 个答案:

答案 0 :(得分:6)

System.arraycopy的类型安全替代方案

carr.slice(3, 8).copyToArray(arr, 3)

或者您可以显式迭代索引

(3 until 8).foreach { i => arr(i) = carr(i) }

两者都不是很简洁,你可能希望在Python中使用像arr[3:] = carr[3:]这样更直接的东西,但这是不可能的。

答案 1 :(得分:3)

这是我能够得到的最接近的。

import scala.collection.{GenIterable, mutable}

implicit class RangeOps[A, 
   S1 : ({type L[X] = X => mutable.Seq[A]})#L](as: S1) {

  def update[S3 : ({type L[X] = X => GenIterable[A]})#L]
      (r: Range, bs: S3): Unit =
    r.zip(bs).foreach({ case (i, b) => as(i) = b })
}

我希望能够写arr(a to b) = ...。但遗憾的是,由于该方法必须命名为updateyou can't use an implicit class to overload a method,因此必须明确地包装数组。哪种方式打败了目的。

val arr = (1 to 10).toArray
RangeOps(arr)(4 to 8 by 2) = Stream from 30
// arr = [1, 2, 3, 4, 30, 6, 31, 8, 32, 10]

编辑 - 对于启发,这是一个简化的版本,它删除了丑陋的泛型,只适用于Array

implicit class RangeOps[A](as: Array[A]) {

  def update(r: Range, bs: Iterable[A]): Unit =
    r.zip(bs).foreach({ case (i, b) => as(i) = b })
}

答案 2 :(得分:1)

此解决方案使用较少的索引来解决错误:

scala> val is = (1 to 10).toArray
is: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> val v = is.view.slice(2,7)
v: scala.collection.mutable.IndexedSeqView[Int,Array[Int]] = SeqViewS(...)

scala> val patch = Array(111,222,333,444,555,666,777,888)
patch: Array[Int] = Array(111, 222, 333, 444, 555, 666, 777, 888)

scala> val it = patch.iterator
it: Iterator[Int] = non-empty iterator

scala> v transform (_ => it.next)
res0: v.type = SeqViewS(...)

scala> is
res1: Array[Int] = Array(1, 2, 111, 222, 333, 444, 555, 8, 9, 10)

scala> implicit class `seq update from`[A](ss: collection.mutable.Seq[A]) { def updateFrom(from: Iterable[A]) = { val it = from.iterator ; ss transform (_ => it.next) }}
defined class seq$u0020update$u0020from

scala> v updateFrom (990 to 999)
res2: scala.collection.mutable.Seq[Int] = SeqViewS(...)

scala> is
res3: Array[Int] = Array(1, 2, 990, 991, 992, 993, 994, 8, 9, 10)