Day 13f: Using Vectors with Enums, Structs, and Custom Types
Introduction
Vectors can hold more than just simple data types like integers or strings; they can also store complex data structures such as structs and enums. In this session, we will explore how vectors interact with these custom types, pattern matching for enums, managing nested vectors, and how ownership rules apply when working with complex data in vectors.
Storing Custom Structs in Vectors
Vectors can store custom data types like structs. This allows you to create collections of complex objects. Let's look at an example where we store a struct in a vector.
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let mut points = Vec::new();
points.push(Point { x: 1, y: 2 });
points.push(Point { x: 3, y: 4 });
println!("{:?}", points); // Output: [Point { x: 1, y: 2 }, Point { x: 3, y: 4 }]
}
Working with Vectors of Enums
Vectors can also store enums with multiple variants. You can use pattern matching to access the correct variant and perform different operations depending on the variant type.
#[derive(Debug)]
enum Shape {
Circle(f64),
Rectangle(f64, f64),
}
fn main() {
let shapes = vec![
Shape::Circle(3.0),
Shape::Rectangle(2.0, 4.0),
];
for shape in shapes {
match shape {
Shape::Circle(radius) => println!("Circle with radius: {}", radius),
Shape::Rectangle(width, height) => println!("Rectangle with width {} and height {}", width, height),
}
}
}
Managing Nested Vectors
You can create vectors that contain other vectors, enabling the construction of multi-dimensional structures like grids or matrices.
fn main() {
let matrix = vec![
vec![1, 2, 3],
vec![4, 5, 6],
vec![7, 8, 9],
];
println!("{:?}", matrix);
}
Ownership and Borrowing with Custom Types
Ownership rules apply when working with custom types inside vectors, just like they do with primitive types. You can borrow or move ownership of structs and enums stored in a vector.
#[derive(Debug)]
struct User {
username: String,
}
fn main() {
let users = vec![
User { username: String::from("Alice") },
User { username: String::from("Bob") },
];
// Borrowing
for user in &users {
println!("Username: {}", user.username);
}
// Moving ownership
let first_user = users.into_iter().next().unwrap();
println!("First user: {:?}", first_user);
}
Conclusion
Vectors are powerful when combined with Rust’s custom types like structs and enums. They allow you to create and manipulate collections of complex data, making them incredibly useful for real-world applications.