Start learning free

LESSON 272 OF 677 · TUPLES, SORTING & BUILT-INS

Positive Squares in Scala: filter, Then map

Practice Read the full explanation

You get an ArrayBuffer of integers, nums.

Return a new ArrayBuffer with the square of every number above 0. A number's square is the number times itself.

Keep the squares in the order of their numbers in nums.

Leave out 0 and the negative numbers. If no number is above 0, return an empty ArrayBuffer.

 

Example 1:

Input: nums = [3, -1, 0, 4]
Output: [9, 16]
Explanation: Only 3 and 4 are above 0.
3 times 3 is 9, and 4 times 4 is 16.

Example 2:

Input: nums = [-5, -2, 0]
Output: []
Explanation: No number is above 0.

Example 3:

Input: nums = [1, 2, 3]
Output: [1, 4, 9]
Explanation: Every number is above 0, so every number is squared.

 

Constraints:

  • nums may be empty.
  • Every number is between -1000 and 1000.
STEP 1 OF 2
    Ctrl + Enter to check

    SCALA · TUPLES, SORTING & BUILT-INS

    Positive Squares in Scala, explained

    Problem overview

    positiveSquares gets an ArrayBuffer[Int] called nums, which may be empty, with numbers from -1000 to 1000. It returns a new buffer with the square of every number above 0, in the order of the numbers. Zero and negative numbers are left out, and if nothing is above 0, the result is an empty buffer.

    • [3, -1, 0, 4] gives [9, 16].
    • [-5, -2, 0] gives [].
    • [1, 2, 3] gives [1, 4, 9].

    Approach

    Two things happen: some numbers are dropped, and the rest are changed. Dropping is filter, and changing is map. Chain them, with filter first: keep the numbers above 0, then square what is left.

    The order matters. Squaring first turns -3 into 9, and 9 is above 0, so a filter after the squaring cannot tell that the number was negative. For [3, -1, 0, 4], squaring first and filtering second gives ArrayBuffer(9, 1, 16), with the 1 that came from -1. Filtering first gives the right ArrayBuffer(9, 16).

    Step by step

    1. Call filter on nums with num => num > 0. Zero is not above 0, so it is left out too.
    2. Call map on that result with num => num * num.
    3. Keep the result in a val named squares and return it.

    The solution in Scala

    class Solution {
        def positiveSquares(nums: ArrayBuffer[Int]): ArrayBuffer[Int] = {
            val squares = nums.filter(num => num > 0).map(num => num * num)
            return squares
        }
    }
    

    A few details:

    • The chain reads left to right: filter, then map. Each call returns a new ArrayBuffer, and nums is unchanged.
    • When no number passes, filter returns an empty buffer, and map on an empty buffer returns an empty buffer. The empty input works the same way, so no special case is needed.
    • The largest square is 1000 times 1000, which is 1,000,000. It fits easily in an Int, whose limit is a little over two billion.

    The same thing with a loop

    The loop version shows what the chain does in one pass:

    val squares = ArrayBuffer[Int]()
    for (num <- nums) {
        if (num > 0) {
            squares += num * num
        }
    }
    

    For [3, -1, 0, 4] it gives ArrayBuffer(9, 16), the same as the chain. The if is the filter and the num * num is the map. The chain builds an in-between buffer after filter, which is fine at this size and keeps each idea on its own call.

    Scala also has collect, which can do both in one call: nums.collect { case n if n > 0 => n * n } returns ArrayBuffer(9, 16) as well. The filter and map pair is the form this lesson teaches.

    Testing

    [3, -1, 0, 4]   ArrayBuffer(9, 16)
    [-5, -2, 0]     ArrayBuffer()
    [1, 2, 3]       ArrayBuffer(1, 4, 9)
    []              ArrayBuffer()
    

    Edge cases

    • Empty input. Both calls return an empty buffer, so the function returns ArrayBuffer() without any special check.
    • Repeated numbers. Nothing removes duplicates. A buffer holding 2 twice gives 4 twice.
    • Only zeros and negatives. The filter removes everything, and the answer is the empty buffer the lesson asks for.
    • All positive. The filter keeps everything, and the result is just the square of each number in the original order.

    Common mistakes

    • Mapping before filtering. The squares are never negative, so the filter drops nothing useful, as shown above.
    • Using >= 0. That keeps 0 and returns an extra 0 in the result.
    • Squaring with ^. In Scala ^ is a bitwise operator, not a power. Use num * num.
    Keep going with Scala500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free