Search code examples
listscalaarraybuffer

Scala: Applying a linear operation on all elements of an ArrayBuffer, and also checking bounds


My question is a two-parter.

Part 1

I have an ArrayBuffer of tuples (x,y). I have a tuple, (deltaX,deltaY), which can look like (-1,0) (as an example) to designate the change to apply to all tuples of the ArrayBuffer.

In Python it would be something like:

newBuffer = [(x+deltaX,y+deltaY) for x,y in oldBuffer]

Part 2

Is there a way to check a conditional on all the items in the ArrayBuffer? In my case I wish to ensure all coordinates are within bounds, so something like (to again use the Python equivalent):

if all(0<=x<xBound and 0<=y<yBound for x,y in buffer)

I can do all these things with lots of very long and annoying code but I am wondering if there is a smarter way.


Solution

  • The first one is a simple map:

    val (dx, dy) = (-1, 0)
    val (xBound, yBound) = (4, 3)
    val tuples = Array(1 -> 2, 2 -> 4, 3 -> 0)
    
    tuples.map { case (x, y) => (x + dx, y + dy) }
    

    And the second one is a use of exists or forall:

    tuples.exists { case (x, y) => x >= xBound || y >= yBound }
    tuples.forall { case (x, y) => x < xBound && y < yBound }
    

    You might also want to use filter and then check isEmpty, or nonEmpty:

    tuples.filter { case (x, y) => x < xBound && y < yBound }.isEmpty
    tuples.filter { case (x, y) => x >= xBound || y > yBound }.nonEmpty
    

    Scala has many syntactic alternatives that you may come across. Here are some examples:

    tuples.map(tuple => (tuple._1 + dx) -> (tuple._2 + dy))
    tuples forAll { tuple =>
        val (x, y) = tuple
        x < xBound && y < yBound
    }
    tuples.filter(_._1 < xBound).filter(_._2 < yBound).isEmpty
    
    for { (x, y) <- tuples } yield (x + dx, y + dy)
    
    (for {
        (x, y) <- tuples
        if x < xBound
        if y < yBound
    } yield (x, y)).isEmpty