How can I achieve multiple step in scala range
Like this: var r = 1 to 100 by (2, 3, 4)
And the last number 4, if there are more to step, will be the repeat step.
or bonus: something like with mode
1. var = 1 to 100 by (2, 3, 4) review // review steps from 2, 3, 4 again.
2. var = 1 to 100 by (2, 3, 4) last // use last number as final steps.
3. var = 1 to 100 by (2, 3, 4) random // use steps randomly within these numbers.
4. var = 1 to 100 by (2, 3, 4) reverse // use steps in reverse and reverse manner.
import scala.collection.immutable.Stream
import scala.collection.mutable.ListBuffer
import scala.util.Random
abstract class RangeX(override val head: Int, val end: Int, var step: Int) extends Stream[Int] {
override val tailDefined = false
override val isEmpty = head > end
def by(steps: Seq[Int]) = {
StepVariant(this, steps)
}
def byGroup(steps: Seq[Int]) = {
StepVariantInGroup(this, steps)
}
def steps(steps: Seq[Int])(fn_steps: (Seq[Int], Int) => Int) = {
var acc = new ListBuffer[Int]()
this.zipWithIndex.foreach {
case (i, idx) =>
acc += i
this.step = fn_steps(steps, idx)
}
acc.toList
}
def stepsByGroup(steps: Seq[Int])(fn_steps: (Seq[Int], Int) => Int) = {
val ls = this.steps(steps)(fn_steps)
var acc = new ListBuffer[List[Int]]()
val lidx = ls.length - 1
(1 to lidx).foreach { i =>
acc += (ls(i - 1) to ls(i) - 1).toList
}
acc.toList
}
case class StepVariant(streams: RangeX, steps: Seq[Int]) {
def repeating_steps = streams.steps(steps)(RangeX.repeating_steps)
def repeat_last_step = streams.steps(steps)(RangeX.repeat_last_step)
def random_steps = streams.steps(steps)(RangeX.random_steps)
def reversing_steps = streams.steps(steps)(RangeX.reversing_steps)
}
case class StepVariantInGroup(streams: RangeX, steps: Seq[Int]) {
def repeating_steps = streams.stepsByGroup(steps)(RangeX.repeating_steps)
def repeat_last_step = streams.stepsByGroup(steps)(RangeX.repeat_last_step)
def random_steps = streams.stepsByGroup(steps)(RangeX.random_steps)
def reversing_steps = streams.stepsByGroup(steps)(RangeX.reversing_steps)
}
}
class RangeSlaveX(_head: Int, _end: Int, _step: Int, val master: RangeX) extends RangeX(_head, _end, _step) {
override def tail = if (isEmpty) Stream.Empty else new RangeSlaveX(head + master.step, end, master.step, master)
}
class RangeMasterX(_head: Int, _end: Int, _step: Int) extends RangeX(_head, _end, _step) {
override def tail = if( isEmpty ) Stream.Empty else new RangeSlaveX(head + step, end, step, this)
}
object RangeX {
implicit def toRangeX(range: Range): RangeX = new RangeMasterX(range.start, range.end, range.step)
def apply(head: Int, end: Int, step: Int) = new RangeMasterX(head, end, step)
def repeating_steps(steps: Seq[Int], idx: Int): Int = {
val size = steps.size
steps( idx % size )
}
def repeat_last_step(steps: Seq[Int], idx: Int): Int = {
val len = steps.length - 1
steps(if( idx >= len) len else idx)
}
def random_steps(steps: Seq[Int], idx: Int): Int = {
Random.shuffle(steps).head
}
def reversing_steps(steps: Seq[Int], idx: Int): Int = {
val size = steps.size
val lidx = size - 1
val forward = ((idx / size) % 2) == 0
if(forward) {
steps( idx % size )
} else {
steps( lidx - (idx % size))
}
}
}
scala> import RangeX._
import RangeX._
Method Chaining Way: - by and byGroup
scala> 1 to 20 byGroup Seq(1, 2, 3) reversing_steps
res0: List[List[Int]] = List(List(1), List(2, 3), List(4, 5, 6), List(7, 8, 9), List(10, 11), List(12), List(13), List(14, 15), List(16, 17, 18))
scala> 1 to 20 byGroup Seq(1, 2, 3) random_steps
res1: List[List[Int]] = List(List(1, 2, 3), List(4, 5), List(6, 7, 8), List(9, 10), List(11, 12), List(13, 14, 15), List(16, 17, 18))
scala> 1 to 20 byGroup Seq(1, 2, 3) repeating_steps
res2: List[List[Int]] = List(List(1), List(2, 3), List(4, 5, 6), List(7), List(8, 9), List(10, 11, 12), List(13), List(14, 15), List(16, 17, 18), List(19))
scala> 1 to 20 byGroup Seq(1, 2, 3) repeat_last_step
res3: List[List[Int]] = List(List(1), List(2, 3), List(4, 5, 6), List(7, 8, 9), List(10, 11, 12), List(13, 14, 15), List(16, 17, 18))
scala> 1 to 20 by Seq(1, 2, 3) reversing_steps
res4: List[Int] = List(1, 2, 4, 7, 10, 12, 13, 14, 16, 19)
scala> 1 to 20 by Seq(1, 2, 3) random_steps
res5: List[Int] = List(1, 2, 3, 6, 8, 11, 13, 15, 17, 19, 20)
scala> 1 to 20 by Seq(1, 2, 3) repeating_steps
res6: List[Int] = List(1, 2, 4, 7, 8, 10, 13, 14, 16, 19, 20)
scala> 1 to 20 by Seq(1, 2, 3) repeat_last_step
res7: List[Int] = List(1, 2, 4, 7, 10, 13, 16, 19)
Functional Way: - steps and stepsByGroup
scala> (1 to 20).steps(Seq(1, 2, 3))(reversing_steps)
res12: List[Int] = List(1, 2, 4, 7, 10, 12, 13, 14, 16, 19)
scala> (1 to 20).steps(Seq(1, 2, 3))(random_steps)
res13: List[Int] = List(1, 4, 6, 8, 10, 12, 14, 16, 17, 18, 20)
scala> (1 to 20).steps(Seq(1, 2, 3))(repeating_steps)
res11: List[Int] = List(1, 2, 4, 7, 8, 10, 13, 14, 16, 19, 20)
scala> (1 to 20).steps(Seq(1, 2, 3))(repeat_last_step)
res15: List[Int] = List(1, 2, 4, 7, 10, 13, 16, 19)
scala> (1 to 20).stepsByGroup(Seq(1, 2, 3))(reversing_steps)
res17: List[List[Int]] = List(List(1), List(2, 3), List(4, 5, 6), List(7, 8, 9), List(10, 11), List(12), List(13), List(14, 15), List(16, 17, 18))
scala> (1 to 20).stepsByGroup(Seq(1, 2, 3))(random_steps)
res18: List[List[Int]] = List(List(1, 2), List(3, 4), List(5), List(6), List(7), List(8, 9), List(10, 11), List(12, 13), List(14, 15, 16), List(17, 18, 19))
scala> (1 to 20).stepsByGroup(Seq(1, 2, 3))(repeating_steps)
res19: List[List[Int]] = List(List(1), List(2, 3), List(4, 5, 6), List(7), List(8, 9), List(10, 11, 12), List(13), List(14, 15), List(16, 17, 18), List(19))
scala> (1 to 20).stepsByGroup(Seq(1, 2, 3))(repeat_last_step)
res20: List[List[Int]] = List(List(1), List(2, 3), List(4, 5, 6), List(7, 8, 9), List(10, 11, 12), List(13, 14, 15), List(16, 17, 18))
How's my revise implementation ^. Seed idea from @Piro implementation link . Thx.
Step Variants
review is repeating_steps
last is repeat_last_step
random is random_steps
reverse is reversing_steps
I wish Sir Martin Odersky add these kind of Range features by(Seq(1,2,3)) *_steps
and byGroup(Seq(1,2,3)) *_steps
in next Scala release :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.