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)
答案 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) = ...
。但遗憾的是,由于该方法必须命名为update
和you 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)