Rust Vector Collection Tutorial

In this Rust tutorial we learn about the vector collection, an array that can be be resized by pushing or removing items from its stack.

We learn the macro and new() method to instantiate a vector struct, how to add and remove elements and how to access elements without Rust having a panic.

Lastly, we look at how to find out if a value exists inside a vector.

Here's a table of contents of what you'll learn in this lesson:
(click on a link to skip to its section)

Let's jump right in.

What is a vector

A vector is a generic collection that can be resized. We can think of it as a resizable array.

Like an array, a vector has a corresponding numerical index and will store its values in contiguous memory blocks on the heap.

The main benefit of a vector is that it can grow and shrink at runtime. Values can be appended to the end of a vector, making it similar to a stack in other languages such as C#.

How to create (instantiate) a new vector

Rust provides us with two methods to create a new vector. We can create a new vector instance by instatiation or via a specialized macro.

The macro is the easiest so let’s start with that.

Syntax: instantiate a vector with a macro
  let vector_name = vec![value_1, value_2, ...];
Example: instantiate a vector with a macro
fn main() {

    let num = vec![10, 20, 30, 40, 50];

}

In the example above, we create a new int32 vector with 5 numerical values. The macro is typically used to to create a vector when we know at least one value beforehand.

The second method is by instantiation (creating a new instance of the vector struct).

To instantiate a new vector, we have to give it a type between the angle brackets as well as use the new() static method.

Syntax: instantiate a vector with new()
  let vector_name: Vec<type> = Vec::new();
Example: instantiate a vector with new()
fn main() {

    let num: Vec<i32> = Vec::new();

}

In the example above, we instantiate a new int32 vector with no values. Instantiation is used to create a vector when we don’t know which values it will hold, only the type.

How to access vector values

Rust provides us with two methods to access elements in a vector. We can access values with either the indexer, or with the get() method.

Let’s take a look at the indexer first.

Syntax: access vector values with the indexer
  vector_name[index];
Example: access vector values with the indexer
fn main() {

    let num = vec![10, 20, 30, 40, 50];

    println!("num[0]: {}", num[0]);
    println!("num[1]: {}", num[1]);
    println!("num[2]: {}", num[2]);
    println!("num[3]: {}", num[3]);
    println!("num[4]: {}", num[4]);

}

Remember that any array or collection with a numerical index will start at index 0 and not 1.

The problem with the indexer is that when we try to access an element that doesn’t exist, Rust will panic and the program will crash.

The solution is to either write an if statement with the contains() method (covered further down below), or use the get() method which won’t cause Rust to panic.

Syntax: access vector values with get()
  vector_name.get(index);
Example: access vector values with get()
fn main() {

    let num = vec![10, 20, 30, 40, 50];

    println!("num[0]: {:?}", num.get(0));
    println!("num[1]: {:?}", num.get(1));
    println!("num[2]: {:?}", num.get(2));
    println!("num[3]: {:?}", num.get(3));
    println!("num[4]: {:?}", num.get(4));

    // try to access an element that
    // doesn't exist
    println!("num[5]: {:?}", num.get(5));

}

In the example above, when we try to access an element that doesn’t exist, Rust doesn’t panic and instead only prints None (Rust’s version of null).

We can also access a vector in a for loop.

Example: access vector values with a for loop
fn main() {

    let num = vec![10, 20, 30, 40, 50];

    for x in num.iter() {
        println!("{}", x);
    }

}

How to add vector values

To add values to a vector, we push them onto the end of the vector stack with the push() method.

Syntax: push a value into a vector
  vector_name.push(value);
Example: push a value into a vector
fn main() {

    let mut num: Vec<i32> = Vec::new();

    num.push(50);
    num.push(40);
    num.push(30);
    num.push(20);
    num.push(10);

    for x in num.iter() {
        println!("{}", x);
    }

}

In the example above, we push items onto the vector’s stack in reverse order (from 50 to 10). This demonstrates how values are added to the end of the stack.

How to remove vector values

To remove values from a vector, we use the remove() method with the index number of the value we want to remove.

When a value is removed, it will push the remaining values after it down by 1.

Syntax: remove a value from a vector
  vector_name.remove(value);
Example: remove a value from a vector
fn main() {

    let mut num = vec![10, 20, 30, 40, 50];

    // remove [2] (30)
    num.remove(2);

    println!("num[0]: {}", num[0]);
    println!("num[1]: {}", num[1]);
    println!("num[2]: {}", num[2]);
    println!("num[3]: {}", num[3]);

}

In the example above, we remove the element at index 2 (30). The values are shifted to take the space of removed elements to 40 will now occupy index 2.

How to find a value inside a vector

We can check if a value exists inside a vector by using the contains() method.

Syntax: check if a vector contains a value
  vector_name.contains(&value);
Example: check if a vector contains a value
fn main() {

    let mut num = vec![10, 20, 30, 40, 50];

    if num.contains(&30) {
        println!("The vector contains the value 30");
    } else {
        num.push(30);
    }

}

In the example above, we check if the vector contains the value 30. If it does, print out a simple message, otherwise add the value.

Summary: Points to remember

  • A vector is a resizable collection of items of the same type, similar to an array.
  • We create a vector with a macro, or instantiate a new instance with the new() method.
  • We access values with the indexer, or with the get() method.
    • The get() method won’t panic if we try to access a value that doesn’t exist.
  • We add an element to a vector with the push() method.
  • We remove a vector element with the remove() method.
    • When an element is removed, those above it will be shifted down one (-1 index).
  • We can test if a value exists within a vector with the contains() method.