Vectors
Using Vec<T> for dynamic arrays.
Vectors
Vec<T> is a dynamic array that stores values of the same type.
Creating a Vector
RUSTlet v: Vec<i32> = Vec::new(); let v = vec![1, 2, 3]; // Using macro
Adding Values
RUSTlet mut v = Vec::new(); v.push(5); v.push(6); v.push(7);
Accessing Values
RUSTlet v = vec![1, 2, 3, 4, 5]; let third: &i32 = &v[2]; // Index - panics if out of bounds let third: Option<&i32> = v.get(2); // Safe - Option
Iteration
RUSTlet v = vec![100, 32, 57]; for i in &v { println!("{}", i); } // Modifying during iteration let mut v = vec![100, 32, 57]; for i in &mut v { *i += 50; }
Using Enum to Store Different Types
RUSTenum SpreadsheetCell { Int(i32), Float(f64), Text(String), } let row = vec![ SpreadsheetCell::Int(3), SpreadsheetCell::Text(String::from("blue")), SpreadsheetCell::Float(10.12), ];
Code Examples
Basic Vector
Creating and using a vector
fn main() {
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);
println!("Vector: {:?}", v);
let v2 = vec![4, 5, 6];
println!("Vector2: {:?}", v2);
}Explanation:
Vec::new() creates an empty vector. The vec![] macro creates a vector with initial values. The push() method adds elements.
Accessing Values
Accessing vector elements
fn main() {
let v = vec![1, 2, 3, 4, 5];
let third = &v[2];
println!("Third element: {}", third);
match v.get(2) {
Some(third) => println!("Third element: {}", third),
None => println!("No third element"),
}
match v.get(100) {
Some(value) => println!("Value: {}", value),
None => println!("No 100th element"),
}
}Explanation:
The v[index] syntax panics if the index is invalid. v.get(index) returns an Option, which is safer.
Iteration
Iterating through a vector
fn main() {
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;
}
println!("Modified vector: {:?}", v);
}Explanation:
The for loop can be immutable (&v) or mutable (&mut v). In mutable iteration, you need to dereference the value with the * operator.
Blockchain: Transaction Vector
Using vectors to store blockchain transactions
struct Transaction {
from: String,
to: String,
amount: u64,
}
fn main() {
let mut transactions = Vec::new();
transactions.push(Transaction {
from: String::from("0xAlice"),
to: String::from("0xBob"),
amount: 100,
});
transactions.push(Transaction {
from: String::from("0xBob"),
to: String::from("0xCharlie"),
amount: 50,
});
println!("Block contains {} transactions", transactions.len());
for (index, tx) in transactions.iter().enumerate() {
println!("Tx {}: {} -> {} ({} tokens)",
index + 1, tx.from, tx.to, tx.amount);
}
}Explanation:
Blocks contain vectors of transactions. Vectors are perfect for this because blocks can have varying numbers of transactions. We can iterate through them to process each transaction.
Blockchain: Chain of Blocks
Using vectors to represent blockchain
struct Block {
index: u64,
hash: String,
}
struct Blockchain {
blocks: Vec<Block>,
}
impl Blockchain {
fn new() -> Self {
Blockchain { blocks: Vec::new() }
}
fn add_block(&mut self, block: Block) {
self.blocks.push(block);
}
fn height(&self) -> usize {
self.blocks.len()
}
fn get_latest(&self) -> Option<&Block> {
self.blocks.last()
}
}
fn main() {
let mut chain = Blockchain::new();
chain.add_block(Block { index: 0, hash: String::from("genesis") });
chain.add_block(Block { index: 1, hash: String::from("hash1") });
chain.add_block(Block { index: 2, hash: String::from("hash2") });
println!("Blockchain height: {}", chain.height());
if let Some(latest) = chain.get_latest() {
println!("Latest block: index {}, hash {}", latest.index, latest.hash);
}
}Explanation:
A blockchain is essentially a vector of blocks. Each block is added to the end, and we can access the latest block or iterate through all blocks. This is the foundation of blockchain data structures.
Exercises
Vector Operations
Create a vector, add elements, and print all elements!
Starter Code:
fn main() {
}Blockchain: Transaction List
Create a vector of transaction amounts and calculate total!
Starter Code:
fn main() {
}