1
将列表拆分成特定数量的块的最快方法是什么?我希望块的大小是随机的,但所有的块至少包含一个元素。将一个列表拆分为固定数量的随机大小的子列表
将列表拆分成特定数量的块的最快方法是什么?我希望块的大小是随机的,但所有的块至少包含一个元素。将一个列表拆分为固定数量的随机大小的子列表
我不知道这是否是做到这一点的最快捷的方式,但我认为这样的事情应该有相当不错的发行工作:
import scala.util.Random
def split[T](list: List[T], chunks: Int): List[List[T]] =
if (chunks == 0) Nil
else if (chunks == 1) List(list)
else {
val avg = list.size/chunks
val rand = (1.0 + Random.nextGaussian/3) * avg
val index = (rand.toInt max 1) min (list.size - chunks)
val (h, t) = list splitAt index
h +: split(t, chunks - 1)
}
结果:
split(1 to 100 toList, 10)
List[List[Int]] = List(
List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14),
List(15, 16, 17, 18, 19, 20, 21),
List(22, 23, 24, 25, 26, 27, 28),
List(29, 30, 31, 32, 33, 34, 35, 36, 37, 38),
List(39, 40, 41, 42, 43),
List(44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54),
List(55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70),
List(71, 72, 73, 74, 75),
List(76, 77, 78, 79, 80, 81, 82, 83, 84),
List(85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100)
)
编辑:这里效率更高,尽管不太优雅的尾递归版本。它以相反的方式构建结果列表,因为在列表结尾处调用带索引的splitAt将以O(n * n)复杂度结束。
def split[T](list: List[T], chunks: Int): List[List[T]] = {
@tailrec
def split[T](list: List[T], chunks: Int, size: Int, result: List[List[T]]): List[List[T]] =
if (chunks == 0) result
else if (chunks == 1) list +: result
else {
val avg = size/chunks
val rand = (1.0 + Random.nextGaussian/3) * avg
val index = (rand.toInt max 1) min (size - chunks)
val (h, t) = list splitAt index
split(t, chunks - 1, size - index, h +: result)
}
split(list, chunks, list.size, Nil).reverse
}
adamwy如何使函数尾递归来避免大输入引起的堆栈溢出错误? – Panayotis