Skip to content

Commit

Permalink
Slice improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
skozlov committed Aug 17, 2024
1 parent ca0cbba commit ba50892
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 1 deletion.
48 changes: 47 additions & 1 deletion src/main/scala/com/github/skozlov/commons/collection/Slice.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ trait SliceOps[
] extends IndexedSeqView[A] {
this: SubSlice =>

import SliceOps._
import SliceOps.*

def underlying: Underlying
def from: Int
Expand Down Expand Up @@ -59,6 +59,52 @@ trait SliceOps[
override def takeRight(n: Int): SubSlice = drop(length - math.max(n, 0))

override def dropRight(n: Int): SubSlice = take(length - math.max(n, 0))

override def tail: SubSlice = {
if (isEmpty) {
throw new UnsupportedOperationException("Empty Slice doesn't have .tail")
}
drop(1)
}

override def init: SubSlice = {
if (isEmpty) {
throw new UnsupportedOperationException("Empty Slice doesn't have .init")
}
dropRight(1)
}

override def tails: Iterator[SubSlice] = {
for (numDrop <- Iterator.range(0, length + 1)) yield drop(numDrop)
}

override def inits: Iterator[SubSlice] = {
for (numDrop <- Iterator.range(0, length + 1)) yield dropRight(numDrop)
}

override def sliding(size: Int, step: Int): Iterator[SubSlice] = {
require(size >= 1, s"Too small size: $size")
require(step >= 1, s"Too small step: $step")
Iterator
.iterate(0 until size) { range =>
(range.start + step) until (range.end + step)
}
.takeWhile { _.start < length }
.map { range =>
this.slice(
from = range.start,
until = math.min(range.end, length),
)
}
}

override def sliding(size: Int): Iterator[SubSlice] = {
sliding(size, step = 1)
}

override def grouped(size: Int): Iterator[SubSlice] = {
sliding(size, step = size)
}
}

object SliceOps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,85 @@ class WritableSliceTest extends Test {
(slice dropRight 2).toSeq shouldBe Seq()
(slice dropRight 3).toSeq shouldBe Seq()
}

test("tail") {
val underlying = Array(1, 2, 3, 4, 5)
the[UnsupportedOperationException] thrownBy {
WritableSlice(underlying)(from = 1, until = 1).tail
} should have message "Empty Slice doesn't have .tail"
WritableSlice(underlying)(from = 1, until = 2).tail.toSeq shouldBe Seq()
WritableSlice(underlying)(from = 1, until = 4).tail.toSeq shouldBe Seq(3, 4)
}

test("init") {
val underlying = Array(1, 2, 3, 4, 5)
the[UnsupportedOperationException] thrownBy {
WritableSlice(underlying)(from = 1, until = 1).init
} should have message "Empty Slice doesn't have .init"
WritableSlice(underlying)(from = 1, until = 2).init.toSeq shouldBe Seq()
WritableSlice(underlying)(from = 1, until = 4).init.toSeq shouldBe Seq(2, 3)
}

test("tails") {
val underlying = Array(1, 2, 3, 4)
(WritableSlice(underlying)(from = 1, until = 1).tails map { _.toSeq }).toSeq
.shouldBe(Seq(Seq()))
(WritableSlice(underlying)(from = 1, until = 3).tails map { _.toSeq }).toSeq
.shouldBe(Seq(Seq(2, 3), Seq(3), Seq()))
}

test("inits") {
val underlying = Array(1, 2, 3, 4)
(WritableSlice(underlying)(from = 1, until = 1).inits map { _.toSeq }).toSeq
.shouldBe(Seq(Seq()))
(WritableSlice(underlying)(from = 1, until = 3).inits map { _.toSeq }).toSeq
.shouldBe(Seq(Seq(2, 3), Seq(2), Seq()))
}

test("sliding") {
val slice = WritableSlice(Array(1, 2, 3, 4, 5, 6, 7))(from = 1, until = 6)
slice.toSeq shouldBe Seq(2, 3, 4, 5, 6)
slice.slice(from = 0, until = 0).sliding(size = 1).toSeq shouldBe Seq()
(slice.sliding(size = 1) map { _.toSeq }).toSeq shouldBe Seq(
Seq(2),
Seq(3),
Seq(4),
Seq(5),
Seq(6),
)
(slice.sliding(size = 2) map { _.toSeq }).toSeq shouldBe Seq(
Seq(2, 3),
Seq(3, 4),
Seq(4, 5),
Seq(5, 6),
Seq(6),
)
(slice.sliding(size = 2, step = 2) map { _.toSeq }).toSeq shouldBe Seq(
Seq(2, 3),
Seq(4, 5),
Seq(6),
)
(slice.sliding(size = 2, step = 3) map { _.toSeq }).toSeq shouldBe Seq(
Seq(2, 3),
Seq(5, 6),
)
}

test("grouped") {
val slice = WritableSlice(Array(1, 2, 3, 4, 5, 6, 7))(from = 1, until = 6)
slice.toSeq shouldBe Seq(2, 3, 4, 5, 6)
slice.slice(from = 0, until = 0).grouped(size = 1).toSeq shouldBe Seq()
(slice.grouped(size = 1) map { _.toSeq }).toSeq shouldBe Seq(
Seq(2),
Seq(3),
Seq(4),
Seq(5),
Seq(6),
)
(slice.grouped(size = 2) map { _.toSeq }).toSeq shouldBe Seq(
Seq(2, 3),
Seq(4, 5),
Seq(6),
)
}
}

0 comments on commit ba50892

Please sign in to comment.