Skip to main content

Vectors

  • A vector is a similar collection type provided by the standard library that is allowed to grow or shrink in size.
  • Vectors are implemented using generics.
  • More often, you’ll create a Vec<T> with initial values and Rust will infer the type of value you want to store, so you rarely need to do type annotation.
  • References:

vecs1.rs

fn array_and_vec() -> ([i32; 4], Vec<i32>) {
let a = [10, 20, 30, 40]; // Array

// Create a vector called `v` which contains the exact same elements as in the array `a`.
// Use the vector macro.
// let v = ???;
let v = vec![10, 20, 30, 40];
(a, v)
}

fn main() {
// You can optionally experiment here.
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_array_and_vec_similarity() {
let (a, v) = array_and_vec();
assert_eq!(a, *v);
}
}
  • Rust conveniently provides the vec! macro, which will create a new vector that holds the values you give it.

  • You can specify the vector types the type within angle brackets like Vec<i32>.

  • More often, you’ll create a vector with initial values and Rust will infer the type of value you want to store, so you rarely need to do this type annotation.

  • In this exercise we just need to init new vector using vec! macro.

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

vecs2.rs

fn vec_loop(input: &[i32]) -> Vec<i32> {
let mut output = Vec::new();

for element in input {
// Multiply each element in the `input` slice by 2 and push it to
// the `output` vector.
output.push(element * 2);
}

output
}

fn vec_map_example(input: &[i32]) -> Vec<i32> {
// An example of collecting a vector after mapping.
// We map each element of the `input` slice to its value plus 1.
// If the input is `[1, 2, 3]`, the output is `[2, 3, 4]`.
input.iter().map(|element| element + 1).collect()
}

fn vec_map(input: &[i32]) -> Vec<i32> {
// Here, we also want to multiply each element in the `input` slice
// by 2, but with iterator mapping instead of manually pushing into an empty
// vector.
// See the example in the function `vec_map_example` above.
input.iter().map(|element| element * 2).collect()
}

fn main() {
// You can optionally experiment here.
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_vec_loop() {
let input = [2, 4, 6, 8, 10];
let ans = vec_loop(&input);
assert_eq!(ans, [4, 8, 12, 16, 20]);
}

#[test]
fn test_vec_map_example() {
let input = [1, 2, 3];
let ans = vec_map_example(&input);
assert_eq!(ans, [2, 3, 4]);
}

#[test]
fn test_vec_map() {
let input = [2, 4, 6, 8, 10];
let ans = vec_map(&input);
assert_eq!(ans, [4, 8, 12, 16, 20]);
}
}
  • In this exercise we have 2 task:

  • First is to iterate through a collection manually using for and multiply each element with 2.

    for element in input {
    output.push(element * 2);
    }
  • Second is to iterate through a collection using iterators and multiply each element with 2.

    input.iter().map(|element| element * 2).collect()
    • Calling iter() to a collection will return Iter type.
    • Then calling map() to produces a new iterator which calls given closure on each element of the original iterator. Ref: trait.iterator method.map.
    • collect() can take anything iterable, and turn it into a relevant collection.
    • You can read more about iterators in here: Iteration and the trait here" Iterator Trait.