Rust Vectors
Dynamic, growable arrays in Rust
📈 What are Rust Vectors?
Vectors are dynamic, growable arrays that can change size at runtime. Unlike arrays, vectors are heap-allocated and can store varying amounts of data, making them perfect for collections where the size isn't known at compile time.
fn main() {
// Create a new empty vector
let mut numbers = Vec::new();
// Add elements
numbers.push(1);
numbers.push(2);
numbers.push(3);
println!("Vector: {:?}", numbers);
println!("Length: {}", numbers.len());
}
Output:
Vector: [1, 2, 3]
Length: 3
Vector Characteristics
Dynamic Size
Can grow and shrink at runtime
vec.push(item); vec.pop();
Heap Allocated
Stored on the heap for flexibility
let vec = Vec::new();
Same Type
All elements must be the same type
let nums: Vec = vec![];
Index Access
Access elements by index like arrays
let first = vec[0];
🔹 Creating Vectors
Different ways to create vectors in Rust:
fn main() {
// Empty vector with explicit type
let mut numbers: Vec = Vec::new();
// Using vec! macro with initial values
let fruits = vec!["apple", "banana", "cherry"];
// Vector with repeated values
let zeros = vec![0; 5]; // [0, 0, 0, 0, 0]
// Vector with capacity pre-allocated
let mut with_capacity = Vec::with_capacity(10);
// Add some elements to demonstrate
numbers.push(1);
numbers.push(2);
numbers.push(3);
println!("Numbers: {:?}", numbers);
println!("Fruits: {:?}", fruits);
println!("Zeros: {:?}", zeros);
println!("Capacity: {}", with_capacity.capacity());
}
Output:
Numbers: [1, 2, 3]
Fruits: ["apple", "banana", "cherry"]
Zeros: [0, 0, 0, 0, 0]
Capacity: 10
🔹 Adding and Removing Elements
Vectors can grow and shrink dynamically:
fn main() {
let mut scores = vec![85, 90, 78];
// Add elements to the end
scores.push(92);
scores.push(88);
println!("After push: {:?}", scores);
// Remove and return the last element
let last = scores.pop();
println!("Popped: {:?}", last);
println!("After pop: {:?}", scores);
// Insert at specific position
scores.insert(1, 95); // Insert 95 at index 1
println!("After insert: {:?}", scores);
// Remove at specific position
let removed = scores.remove(2); // Remove element at index 2
println!("Removed: {}", removed);
println!("Final: {:?}", scores);
}
Output:
After push: [85, 90, 78, 92, 88]
Popped: Some(88)
After pop: [85, 90, 78, 92]
After insert: [85, 95, 90, 78, 92]
Removed: 90
Final: [85, 95, 78, 92]
🔹 Accessing Vector Elements
Safe and unsafe ways to access vector elements:
fn main() {
let colors = vec!["red", "green", "blue", "yellow"];
// Direct indexing (can panic if index is invalid)
println!("First color: {}", colors[0]);
// Safe access with get() method
match colors.get(2) {
Some(color) => println!("Third color: {}", color),
None => println!("No color at index 2"),
}
// Safe access for potentially invalid index
match colors.get(10) {
Some(color) => println!("Color at index 10: {}", color),
None => println!("No color at index 10"),
}
// Get first and last elements safely
println!("First: {:?}", colors.first());
println!("Last: {:?}", colors.last());
// Vector length
println!("Number of colors: {}", colors.len());
}
Output:
First color: red
Third color: blue
No color at index 10
First: Some("red")
Last: Some("yellow")
Number of colors: 4
🔹 Iterating Over Vectors
Different ways to iterate through vector elements:
fn main() {
let mut numbers = vec![1, 2, 3, 4, 5];
// Method 1: Immutable iteration
println!("Method 1 - Immutable iteration:");
for num in &numbers {
println!(" {}", num);
}
// Method 2: Mutable iteration
println!("\nMethod 2 - Mutable iteration (doubling values):");
for num in &mut numbers {
*num *= 2;
}
println!(" Doubled: {:?}", numbers);
// Method 3: Taking ownership
println!("\nMethod 3 - Taking ownership:");
for num in numbers {
println!(" Owned: {}", num);
}
// numbers is no longer accessible here
// Method 4: With index using enumerate
let fruits = vec!["apple", "banana", "cherry"];
println!("\nMethod 4 - With index:");
for (index, fruit) in fruits.iter().enumerate() {
println!(" {}: {}", index, fruit);
}
}
Output:
Method 1 - Immutable iteration:
1
2
3
4
5
Method 2 - Mutable iteration (doubling values):
Doubled: [2, 4, 6, 8, 10]
🔹 Vector Methods and Operations
Useful methods for working with vectors:
fn main() {
let mut data = vec![3, 1, 4, 1, 5, 9, 2, 6];
// Length and capacity
println!("Length: {}, Capacity: {}", data.len(), data.capacity());
// Check if empty
println!("Is empty: {}", data.is_empty());
// Contains element
println!("Contains 5: {}", data.contains(&5));
// Clear all elements
let mut temp = data.clone();
temp.clear();
println!("After clear - Length: {}", temp.len());
// Extend with another vector
let more_data = vec![8, 7];
data.extend(more_data);
println!("After extend: {:?}", data);
// Retain elements that match condition
data.retain(|&x| x > 3);
println!("After retain (>3): {:?}", data);
// Sort the vector
data.sort();
println!("After sort: {:?}", data);
}
Output:
Length: 8, Capacity: 8
Is empty: false
Contains 5: true
After clear - Length: 0
After extend: [3, 1, 4, 1, 5, 9, 2, 6, 8, 7]
After retain (>3): [4, 5, 9, 6, 8, 7]
After sort: [4, 5, 6, 7, 8, 9]