我需要混洗ArrayBuffer的一部分,最好是就地,这样就不需要拷贝了。例如,如果一个ArrayBuffer有10个元素,而我想要将元素3-7打乱:
// Unshuffled ArrayBuffer of ints numbered 0-9
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
// Region I want to shuffle is between the pipe symbols (3-7)
0, 1, 2 | 3, 4, 5, 6, 7 | 8, 9
// Example of how it might look after shuffling
0, 1, 2 | 6, 3, 5, 7, 4 | 8, 9
// Leaving us with a partially shuffled ArrayBuffer
0, 1, 2, 6, 3, 5, 7, 4, 8, 9
我已经编写了如下所示的代码,但它需要复制和迭代循环几次。似乎应该有一种更有效的方法来做这件事。
def shufflePart(startIndex: Int, endIndex: Int) {
val part: ArrayBuffer[Int] = ArrayBuffer[Int]()
for (i <- startIndex to endIndex ) {
part += this.children(i)
}
// Shuffle the part of the array we copied
val shuffled = this.random.shuffle(part)
var count: Int = 0
// Overwrite the part of the array we chose with the shuffled version of it
for (i <- startIndex to endIndex ) {
this.children(i) = shuffled(count)
count += 1
}
}
我找不到任何关于与谷歌部分洗牌ArrayBuffer的内容。我假设我将不得不写我自己的方法,但在这样做的时候,我想防止复制。
发布于 2012-03-06 03:31:13
我不完全确定为什么它必须在适当的地方-您可能需要考虑这一点。但是,假设这是正确的做法,这是可以做到的:
import scala.collection.mutable.ArrayBuffer
implicit def array2Shufflable[T](a: ArrayBuffer[T]) = new {
def shufflePart(start: Int, end: Int) = {
val seq = (start.max(0) until end.min(a.size - 1)).toSeq
seq.zip(scala.util.Random.shuffle(seq)) foreach { t =>
val x = a(t._1)
a.update(t._1, a(t._2))
a(t._2) = x
}
a
}
}
您可以像这样使用它:
val a = ArrayBuffer(1,2,3,4,5,6,7,8,9)
println(a)
println(a.shufflePart(2, 7))
编辑:如果你愿意支付中间序列的额外成本,从算法上讲,这是更合理的:
def shufflePart(start: Int, end: Int) = {
val seq = (start.max(0) until end.min(a.size - 1)).toSeq
seq.zip(scala.util.Random.shuffle(seq) map { i =>
a(i)
}) foreach { t =>
a.update(t._1, t._2)
}
a
}
}
发布于 2012-03-06 09:41:59
因为ResizableArray
有一个受保护的成员array
,所以如果可以使用ArrayBuffer
的子类型,就可以直接访问底层数组
import java.util.Collections
import java.util.Arrays
import collection.mutable.ArrayBuffer
val xs = new ArrayBuffer[Int]() {
def shuffle(a: Int, b: Int) {
Collections.shuffle(Arrays.asList(array: _*).subList(a, b))
}
}
xs ++= (0 to 9) // xs = ArrayBuffer(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
xs.shuffle(3, 8) // xs = ArrayBuffer(0, 1, 2, 4, 6, 5, 7, 3, 8, 9)
备注:
java.util.List#subList
的上限是独占的Arrays#asList
不会创建新的元素集:它是由数组本身支持的(因此没有添加或删除方法)a
和Arrays#asList
添加边界检查https://stackoverflow.com/questions/9572408
复制相似问题