Skip to content

Collections

Vector

Vectors allow you to store multiple values next to each other in memory. Vectors can only contain a single type. Enums of the same type count, so you can store multiple kinds of values using an enum. You can create vectors with the new class function, or with the vec! macro.

rust
let v: Vec<i32> = Vec::new();

let v = vec![1, 2, 3];
v.push(5);
v.push(6);
v.push(7);
v.push(8);

enum SpreadsheetCell {
    Int(i32),
    Float(f64),
    Text(String),
}

let row = vec![
    SpreadsheetCell::Int(3),
    SpreadsheetCell::Text(String::from("blue")),
    SpreadsheetCell::Float(10.12),
];

Values can be read from a vector with brackets or the get method. Retrieving from a vector gives you a reference to the element. If you try to access a vector with brackets that is out of the range, then the code will panic.

rust
let v = vec![1, 2, 3, 4, 5];

let third: &i32 = &v[2];

let third: Option<&i32> = v.get(2);

To iterate over a vector, we use the for in syntax. You can also iterate over a mutable vector and mutate the elements.

rust
let v = vec![100, 32, 57];
for i in &v {
    println!("{}", i);
}

let mut v = vec![100, 32, 57];
    for i in &mut v {
        *i += 50;
    }

Strings

String

The String type is part of the Rust standard library instead of imbedded in the core language. It is owned, mutable, growable, and UTF-8 encoded. A String is actually just a wrapper of the Vec<T> type, so a lot of the same methods apply. You can append to a mutable string with push_str which takes a string slice, so it does not take ownership of the item being passed in.

rust
let mut s = String::new();
let s2 = "bar";
s1.push_str(s2);
println!("s2 is {}", s2);

// From string literal
let data = "initial contents";
let s = data.to_string();
let s = "initial contents".to_string();
let s = String::from("initial contents");

Concatenating strings can be done with either the + operator or the format! macro. You can see that s2 is still usable after the concatenation, this is because the add function has the definition fn add(self, s: &str) -> String, meaning the second argument is a string slice and therefore not transfered (&String can be transformed to a &str automatically). format! takes strings and returns another String and doesn't take ownership of any of the arguments.

rust
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used

let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");

let s = format!("{}-{}-{}", s1, s2, s3);

You can iterate over strings by using a for in loop and the chars() function.

rust
for c in "З21".chars() {
    println!("{}", c);
}

&str or String Slice

A string slice is a reference to a part of a String. When writing functions that take a string reference, it is better to use &str because &String is automatically converted to a string slice if passed into a function that takes one.

rust
let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];

Hash Maps

Stores a collection of key-value pairs. The keys must all be the same type, and the values must all be the same type. The get method returns an Option<&V>. For types that implement the Copy trait, they will be copied when inserted into the hash map. Otherwise, like strings, ownership will be transfered. If you insert a reference, the value the reference is pointing to must be valid for the lifetime of the hash map.

rust
use std::collections::HashMap;

let mut scores = HashMap::new();

scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);

let team_name = String::from("Blue");
let score = scores.get(&team_name);

for (key, value) in &scores {
    println!("{}: {}", key, value);
}

scores.insert(String::from("Blue"), 25); // Overwrites
scores.entry(String::from("Blue")).or_insert(50); // Add if not present

// Update value based on previous value
let text = "hello world wonderful world";

let mut map = HashMap::new();

for word in text.split_whitespace() {
    let count = map.entry(word).or_insert(0);
    *count += 1;
}