Start learning free

LESSON 125 OF 679 · ARRAYS - CHALLENGES

First N Items in Rust: Slicing a Vec

Practice Read the full explanation

You get a Vec of integers nums and a number n. Return a Vec with the first n numbers of nums.

Keep them in the same order. When n is 0, return an empty Vec.

 

Example 1:

Input: nums = [3, 8, 1, 9, 4], n = 3
Output: [3, 8, 1]
Explanation: The first 3 numbers are 3, 8 and 1.
The 9 and the 4 are left out.

Example 2:

Input: nums = [5, 6, 7], n = 0
Output: []
Explanation: No numbers are taken, so the result is empty.

Example 3:

Input: nums = [2, 4], n = 2
Output: [2, 4]
Explanation: n is the length of nums, so every number is kept.

 

Constraints:

  • nums has 1 to 10 numbers.
  • Every number is an integer from -1000 to 1000.
  • n is from 0 to the length of nums.
STEP 1 OF 2
    Ctrl + Enter to check

    RUST · ARRAYS - CHALLENGES

    First N Items in Rust, explained

    Problem overview

    The function first_n receives a vector of integers, nums, and a number n. It returns a new vector holding the first n numbers of nums, in the same order. When n is 0 the result is empty, and n is never larger than the length of nums.

    For nums = [3, 8, 1, 9, 4] and n = 3, the answer is [3, 8, 1]: the 9 and the 4 are left out. For nums = [2, 4] and n = 2, every number is kept.

    Approach

    The first n items sit at indexes 0 up to n - 1. A range of indexes selects exactly those, and to_vec() copies them into a new vector. You don't need a loop, and no index arithmetic beyond the range itself.

    Step by step

    1. Take the range 0..n of nums. A Rust range stops before its end, so 0..n covers exactly n indexes. The parameter n is a usize, the type Rust uses for indexes, so it fits in the range as it is, with no conversion.
    2. Call to_vec() on that slice. On its own, nums[0..n] only borrows part of nums and has no fixed size known at compile time, so it can't be returned. to_vec() makes an owned Vec<i32>. Store it in result.
    3. End the function with result on its own line, without a semicolon. Rust returns the last expression of a function body.

    The solution in Rust

    impl Solution {
        fn first_n(nums: Vec<i32>, n: usize) -> Vec<i32> {
            let result = nums[0..n].to_vec();
            result
        }
    }
    

    Writing result; with a semicolon would turn the last line into a statement, and the function would then return nothing, which is a compile error since a Vec<i32> is expected. When n is 0 the range 0..0 is empty, and to_vec() gives an empty vector without any special case.

    Following one call

    Take nums = [3, 8, 1, 9, 4] and n = 3. The slice nums[0..n] holds [3, 8, 1] and has length 3. After to_vec(), result is the vector [3, 8, 1], and nums is still [3, 8, 1, 9, 4]. The input is not changed, which is why the function can take nums without mut. Because the function owns nums anyway, it could also shorten the vector in place with truncate(n), but copying the front part is the idea this lesson practises.

    Why not a loop

    A loop that pushes nums[i] into a new vector for each i from 0 to n - 1 gives the same answer, and it is a fine exercise. The slice does the same work in one expression and cannot get the bounds wrong halfway. In Rust, a range with to_vec() is the usual way to copy a block of consecutive items, so it is worth learning as a single idea: pick a range, then copy.

    Edge cases and common mistakes

    • Off by one. 0..=n includes index n and returns one number too many (and panics when n equals the length).
    • A range past the end. The constraints keep n within the length, so the code needs no guard. Without that promise, nums[0..n] with n too large would panic.
    • Returning the slice. Leaving out to_vec() gives a type mismatch, because the function must return an owned vector.

    Testing

    These results come from running the function on the statement's examples:

    • nums = [3, 8, 1, 9, 4], n = 3 gives [3, 8, 1].
    • nums = [5, 6, 7], n = 0 gives [].
    • nums = [2, 4], n = 2 gives [2, 4].
    Keep going with Rust500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free