🎒 Vectors in Rust: Your Magic Backpack!
Imagine you have a magic backpack that can grow bigger or smaller whenever you need. You can put toys in, take toys out, and even peek at what’s inside. That’s exactly what a Vector is in Rust!
🌟 What is a Vector?
A Vector (or Vec) is like a stretchy bag that holds a list of things. Unlike a regular bag with fixed size, this one grows when you add more stuff!
graph TD A["🎒 Empty Vector"] --> B["Add Apple 🍎"] B --> C["Add Banana 🍌"] C --> D["Add Cherry 🍒"] D --> E["🎒 Vector with 3 items!"]
Real Life Examples:
- Your toy collection that keeps growing
- A list of your favorite songs
- Names of your friends
📦 Creating Vectors
There are two easy ways to create a vector!
Way 1: Start Empty and Add Later
let mut toys: Vec<String> = Vec::new();
// An empty backpack, ready for toys!
Think of this like getting a new, empty backpack on your birthday. It’s empty now, but you’ll fill it with treasures!
Way 2: Use the Magic vec! Spell
let fruits = vec!["apple", "banana", "cherry"];
// Backpack already has 3 fruits!
This is like buying a backpack that already has some things inside. Super convenient!
✨ The vec! Macro - Your Magic Spell
The vec! macro is like saying a magic word that creates a vector instantly with items inside.
// Numbers in your backpack
let numbers = vec![1, 2, 3, 4, 5];
// Colors in your backpack
let colors = vec!["red", "blue", "green"];
// Same item repeated 3 times
let zeros = vec![0; 3]; // [0, 0, 0]
🎯 Quick Comparison
| Method | When to Use |
|---|---|
Vec::new() |
Start empty, add later |
vec![...] |
Know items upfront |
vec![x; n] |
Same item n times |
➕ Updating Vectors
Your magic backpack has special powers to change!
Adding Items with push()
let mut snacks = vec!["cookie"];
snacks.push("candy"); // Now: [cookie, candy]
snacks.push("chips"); // Now: [cookie, candy, chips]
It’s like putting a new toy at the bottom of your backpack!
Removing the Last Item with pop()
let mut snacks = vec!["cookie", "candy"];
let last = snacks.pop();
// last = Some("candy")
// snacks = ["cookie"]
pop() takes out whatever is on top and gives it to you.
Insert at a Specific Spot
let mut letters = vec!['a', 'c'];
letters.insert(1, 'b');
// Now: ['a', 'b', 'c']
Like squeezing a book between two others on a shelf!
Remove from a Specific Spot
let mut nums = vec![1, 2, 3];
nums.remove(1); // Removes the 2
// Now: [1, 3]
👀 Reading Vector Elements
How do you peek inside your backpack?
Way 1: Use Square Brackets []
let pets = vec!["dog", "cat", "bird"];
let first = pets[0]; // "dog"
let second = pets[1]; // "cat"
⚠️ Warning! If you ask for something that doesn’t exist, your program panics (crashes)!
let oops = pets[99]; // 💥 CRASH!
Way 2: Use .get() - The Safe Way
let pets = vec!["dog", "cat", "bird"];
let maybe = pets.get(99);
// Returns None, no crash!
.get() is like a gentle hand that says “Maybe there’s something, maybe not.”
graph TD A["Want Item?"] --> B{Use get or index?} B -->|"pets[i]"| C["Might Crash! 💥"] B -->|"pets.get#40;i#41;"| D["Safe! Returns Option"]
The Option Magic Box
match pets.get(1) {
Some(pet) => println!("Found: {}", pet),
None => println!("Nothing there!"),
}
🔄 Iterating Over Vectors
Iterating means visiting each item one by one, like saying hello to every toy in your backpack!
Just Looking (Borrowing)
let fruits = vec!["apple", "banana"];
for fruit in &fruits {
println!("Hello, {}!", fruit);
}
// fruits still usable here!
Looking and Changing (Mutable Borrow)
let mut scores = vec![1, 2, 3];
for score in &mut scores {
*score += 10; // Add 10 to each
}
// scores = [11, 12, 13]
The * is like opening the box to change what’s inside.
Taking Everything Out
let toys = vec!["ball", "doll"];
for toy in toys {
println!("Playing with {}", toy);
}
// toys is GONE now! Used up.
graph TD A["Iterate Options"] --> B["&vec = Borrow<br/>Look only"] A --> C["&mut vec = Change<br/>Look & modify"] A --> D["vec = Consume<br/>Take ownership"]
📏 Vector Capacity
Your backpack has a secret size - how much it CAN hold before needing to grow!
Length vs Capacity
let mut nums = Vec::with_capacity(10);
nums.push(1);
nums.push(2);
println!("Length: {}", nums.len()); // 2
println!("Capacity: {}", nums.capacity()); // 10
- Length = How many items ARE inside
- Capacity = How many items CAN fit
Why Care About Capacity?
When the backpack gets full, Rust needs to:
- Buy a bigger backpack
- Move everything over
- Throw away the old one
This takes time! If you know you’ll need 1000 items, tell Rust upfront:
// Smart: Reserve space first
let mut big = Vec::with_capacity(1000);
// Less smart: Keep growing
let mut small = Vec::new();
Checking and Reserving
let mut v = vec![1, 2, 3];
v.reserve(100); // Make room for 100 more!
v.shrink_to_fit(); // Trim extra space
🎯 Quick Summary
| Task | Code |
|---|---|
| Create empty | Vec::new() |
| Create with items | vec![1, 2, 3] |
| Add to end | .push(item) |
| Remove from end | .pop() |
| Get safely | .get(index) |
| Loop through | for x in &vec |
| Check size | .len() |
| Check capacity | .capacity() |
🚀 You’re Ready!
You now know how to use Vectors - Rust’s amazing, growable lists! They’re like magic backpacks that:
- ✅ Grow when you need more space
- ✅ Let you peek at any item
- ✅ Let you add and remove things
- ✅ Are super efficient when you plan ahead
Go build something awesome! 🎉
