一次性生成自定义图案编号序列



我想使用函数初始化结构一次性生成以下数字序列:

Array(0, 0, 0, 0, 3, 3, 6, 6, 9, 9, ..., n*3, n*3)

一种方法是:

Array.fill[Int](2)(0) ++ Array.tabulate(4)(_*3)

但我需要将结构第二部分的每个值加倍,即得到0, 0然后3, 3等。如何复制第二个构造的值?

我也想不出一个数学函数来生成这样的序列。

Array(0,0) ++ (0 to 2*n).map(_ / 2 * 3)

考虑单次传递的尾递归解决方案

def pattern(n: Int): List[Int] = {
@tailrec def run(n: Int, acc: List[Int]): List[Int] = {
n match {
case 0 => 0 :: 0 :: 0 :: 0 :: acc
case i => run(i - 1, (i * 3) :: (i * 3) :: acc)
}
}
run(n-1, Nil)
}

你可以这样做:

def create(n: Int): Array[Int] =
Array.tabulate(n)(i => Array.fill(if (i == 0) 4 else 2)(3 * i)).flatten

但是,数组不是平展的最佳数据类型。

这是使用flatMap的可能解决方案:

Array.fill[Int](2)(0) ++ Array.tabulate(4)(_*3).flatMap(x => Array(x, x))

JMH 答案基准

@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.Throughput))
class So59902144 {
def Luis(n: Int) = Array.tabulate(n)(i => Array.fill(if (i == 0) 4 else 2)(3 * i)).flatten
def Dima(n: Int) = Array(0,0) ++ (0 until 2*n).map(_ / 2 * 3)
def SkyWalker(n: Int) = Array.fill[Int](2)(0) ++ Array.tabulate(n)(_*3).flatMap(x => Array(x, x))
def MarioGalic(n: Int) =  {
@tailrec def run(n: Int, acc: List[Int]): List[Int] = {
n match {
case 0 => 0 :: 0 :: 0 :: 0 :: acc
case i => run(i - 1, (i * 3) :: (i * 3) :: acc)
}
}
run(n-1, Nil)
}
val n = 10000
@Benchmark def _Luis = Luis(n)
@Benchmark def _Dima = Dima(n)
@Benchmark def _SkyWalker = SkyWalker(n)
@Benchmark def _MarioGalic = MarioGalic(n)
}
sbt "jmh:run -i 5 -wi 2 -f 1 -t 1 -prof gc bench.So59902144"
[info] Benchmark                   Mode   Cnt        Score       Error   Units
[info] So59902144._Dima            thrpt    5     5178.171 ±   837.780   ops/s
[info] So59902144._Luis            thrpt    5     3649.262 ±   309.027   ops/s
[info] So59902144._MarioGalic      thrpt    5    10926.546 ±  3587.691   ops/s
[info] So59902144._SkyWalker       thrpt    5     6088.413 ±   474.100   ops/s

最新更新