Rust vectors
last modified October 25, 2026
In this article we show how to work with vectors in Rust.
A vector, Vec<T>, is a growable array of
elements of the same type. It is the most commonly used collection in Rust.
The elements are stored contiguously on the heap, so a vector provides fast
indexing and efficient iteration. Unlike an array,
whose size is part of its type, a vector can grow and shrink while the
program runs.
A vector consists of a pointer to the heap buffer, its length (the number of elements), and its capacity (the number of elements the buffer can hold). When the length reaches the capacity, the vector allocates a larger buffer and moves the elements there. The vector owns its elements; when it goes out of scope, the elements are dropped and the memory is freed.
The examples were tested with Rust 1.97 and the 2024 edition. They are run as
Cargo projects with cargo run -q.
Creating vectors
A vector is created with the vec! macro, with the
Vec::new and Vec::with_capacity functions, or by
collecting an iterator.
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
let zeros = vec![0; 5];
let mut words = Vec::new();
for w in ["Hello", "Rust"] {
words.push(w.to_uppercase());
}
let mut data: Vec<i32> = Vec::with_capacity(100);
for i in 0..10 {
data.push(i * 2);
}
let squares: Vec<u32> = (1..=5).map(|x| x * x).collect();
let chars = Vec::from(['a', 'b', 'c']);
let empty: Vec<f64> = Vec::new();
println!("numbers: {numbers:?}");
println!("zeros: {zeros:?}");
println!("words: {words:?}");
println!("data (capacity {}): {data:?}", data.capacity());
println!("squares: {squares:?}");
println!("chars: {chars:?}");
println!("empty: {empty:?}, len {}", empty.len());
}
The example creates vectors in several ways.
let numbers = vec![1, 2, 3, 4, 5]; let zeros = vec![0; 5];
The vec! macro creates a vector from a list of values. The
vec![value; n] form creates a vector with n copies
of the value.
let mut words = Vec::new();
for w in ["Hello", "Rust"] {
words.push(w.to_uppercase());
}
The Vec::new function creates an empty vector, which does not
allocate memory until the first element is added. The element type is
inferred from the push calls.
let mut data: Vec<i32> = Vec::with_capacity(100);
The with_capacity function allocates space for a hundred
elements in advance. The vector is still empty; it can grow to a hundred
elements without reallocating.
let squares: Vec<u32> = (1..=5).map(|x| x * x).collect(); let chars = Vec::from(['a', 'b', 'c']); let empty: Vec<f64> = Vec::new();
The collect method builds a vector from an iterator, and
Vec::from creates it from an array. An empty vector needs a type
annotation if the type cannot be inferred from later use.
$ cargo run -q numbers: [1, 2, 3, 4, 5] zeros: [0, 0, 0, 0, 0] words: ["HELLO", "RUST"] data (capacity 100): [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] squares: [1, 4, 9, 16, 25] chars: ['a', 'b', 'c'] empty: [], len 0
Accessing elements
Elements are accessed by indexing with [] or with the
get method. Indexes start from zero.
fn main() {
let mut fruits = vec!["Apple", "Banana", "Cherry"];
fruits.push("Date");
let first = fruits[0];
let last = fruits[fruits.len() - 1];
println!("first: {first}, last: {last}");
match fruits.get(2) {
Some(fruit) => println!("index 2: {fruit}"),
None => println!("index out of bounds"),
}
if let Some(fruit) = fruits.get(10) {
println!("found: {fruit}");
} else {
println!("index 10 does not exist");
}
println!("{:?} {:?}", fruits.first(), fruits.last());
println!("{:?}", fruits.get(1..3));
}
We get elements by index and with methods that return an
Option.
let first = fruits[0]; let last = fruits[fruits.len() - 1];
Indexing returns the element directly. It panics if the index is out of bounds.
match fruits.get(2) {
Some(fruit) => println!("index 2: {fruit}"),
None => println!("index out of bounds"),
}
The get method returns Option<&T>: a
reference to the element, or None if the index is out of bounds.
The compiler forces us to handle the missing element.
println!("{:?} {:?}", fruits.first(), fruits.last());
println!("{:?}", fruits.get(1..3));
The first and last methods return
None for an empty vector. Given a range, get
returns a slice.
$ cargo run -q
first: Apple, last: Date
index 2: Cherry
index 10 does not exist
Some("Apple") Some("Date")
Some(["Banana", "Cherry"])
Index out of bounds
Rust checks every index at run time. An invalid index causes a panic instead of reading memory outside of the vector.
fn main() {
let fruits: Vec<&str> = "Apple Banana Cherry Date".split(' ').collect();
let idx = fruits.len();
println!("{}", fruits[idx]);
}
The vector has four elements, so the valid indexes are 0 to 3.
println!("{}", fruits[idx]);
The index 4 is equal to the length. The panic message shows the length and
the index. Use indexing when an invalid index is a bug, and get
when the index comes from user input or other uncertain data.
$ cargo run -q thread 'main' (71506) panicked at src/main.rs:5:26: index out of bounds: the len is 4 but the index is 4 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Modifying elements
Elements of a mutable vector can be changed through indexing, mutable references, and methods that change the whole vector.
fn main() {
let mut vals = vec![1, 2, 3, 4, 5];
vals[0] = 10;
if let Some(x) = vals.get_mut(1) {
*x *= 10;
}
if let Some(last) = vals.last_mut() {
*last = 50;
}
vals.swap(2, 3);
println!("{vals:?}");
for x in vals.iter_mut() {
*x += 1;
}
println!("{vals:?}");
vals.reverse();
println!("{vals:?}");
vals.fill(0);
println!("{vals:?}");
}
We change single elements and then all elements at once.
vals[0] = 10;
if let Some(x) = vals.get_mut(1) {
*x *= 10;
}
The get_mut method returns a mutable reference to the element.
We modify the value through the reference with the dereference operator
*.
vals.swap(2, 3);
The swap method exchanges two elements.
for x in vals.iter_mut() {
*x += 1;
}
The iter_mut method returns an iterator of mutable references.
vals.reverse(); vals.fill(0);
The reverse method reverses the order of the elements in place;
fill sets all elements to a value.
$ cargo run -q [10, 20, 4, 3, 50] [11, 21, 5, 4, 51] [51, 4, 5, 21, 11] [0, 0, 0, 0, 0]
Adding elements
Elements are added to the end with push, at a given position
with insert, and from other collections with
extend, append, and
extend_from_slice.
fn main() {
let mut scores = vec![10, 20];
scores.push(30);
println!("{scores:?}");
scores.insert(1, 15);
println!("{scores:?}");
scores.extend([40, 50]);
println!("{scores:?}");
let mut more = vec![60, 70];
scores.append(&mut more);
println!("{scores:?} {more:?}");
scores.extend_from_slice(&[80, 90]);
println!("{scores:?}");
}
We add elements to a vector of scores.
scores.insert(1, 15);
The insert method shifts all following elements to the right,
so it takes time proportional to the length of the vector. Adding to the end
with push is fast.
scores.extend([40, 50]);
The extend method adds the elements of any iterable.
let mut more = vec![60, 70]; scores.append(&mut more);
The append method moves all elements of another vector, which is
left empty.
scores.extend_from_slice(&[80, 90]);
The extend_from_slice method clones the elements of a slice.
$ cargo run -q [10, 20, 30] [10, 15, 20, 30] [10, 15, 20, 30, 40, 50] [10, 15, 20, 30, 40, 50, 60, 70] [] [10, 15, 20, 30, 40, 50, 60, 70, 80, 90]
Removing elements
Vectors provide several removal methods: pop for the last
element, remove for any index, swap_remove for fast
removal when the order does not matter, and truncate and
clear for many elements.
fn main() {
let mut items = vec!["A", "B", "C", "D", "E", "F"];
let last = items.pop();
println!("popped: {last:?}, {items:?}");
let removed = items.remove(1);
println!("removed: {removed}, {items:?}");
let swapped = items.swap_remove(0);
println!("swap_removed: {swapped}, {items:?}");
items.truncate(2);
println!("truncated: {items:?}");
items.clear();
println!("cleared: {items:?}, capacity {}", items.capacity());
let mut empty: Vec<i32> = Vec::new();
println!("{:?}", empty.pop());
}
We remove elements in several ways.
let last = items.pop();
The pop method removes the last element and returns it in an
Option; for an empty vector it returns None.
let removed = items.remove(1);
The remove method returns the element and shifts the following
elements to the left.
let swapped = items.swap_remove(0);
The swap_remove method replaces the removed element with the
last one. It runs in constant time, but changes the order of the elements:
"E" moved to the front.
items.truncate(2); items.clear();
The truncate method keeps only the first elements;
clear removes all of them. Neither method frees the allocated
memory; the capacity remains the same.
$ cargo run -q
popped: Some("F"), ["A", "B", "C", "D", "E"]
removed: B, ["A", "C", "D", "E"]
swap_removed: A, ["E", "C", "D"]
truncated: ["E", "C"]
cleared: [], capacity 6
None
Filtering in place
The retain, dedup, drain,
split_off, and extract_if methods remove groups of
elements.
fn main() {
let mut vals = vec![1, 2, 2, 3, 3, 3, 4, 5, 5, 6];
vals.dedup();
println!("dedup: {vals:?}");
vals.retain(|&x| x % 2 == 0);
println!("retain: {vals:?}");
let mut words = vec!["sky", "Sky", "rock", "ROCK", "rock", "sun"];
words.dedup_by_key(|w| w.to_lowercase());
println!("{words:?}");
let mut nums: Vec<i32> = (1..=10).collect();
let drained: Vec<i32> = nums.drain(2..5).collect();
println!("drained: {drained:?}, left: {nums:?}");
let tail = nums.split_off(4);
println!("{nums:?} {tail:?}");
let mut data = vec![5, 1, 4, 1, 5, 9, 2, 6];
let small: Vec<i32> = data.extract_if(.., |x| *x < 4).collect();
println!("{small:?} {data:?}");
}
We remove duplicates and filter the elements of vectors.
vals.dedup(); vals.retain(|&x| x % 2 == 0);
The dedup method removes consecutive duplicates; to remove all
duplicates, sort the vector first. The retain method keeps only
the elements for which the closure returns true.
words.dedup_by_key(|w| w.to_lowercase());
The dedup_by_key method compares the keys computed by the
closure. Consecutive words that differ only in case are treated as
duplicates.
let drained: Vec<i32> = nums.drain(2..5).collect(); let tail = nums.split_off(4);
The drain method removes a range and returns the removed
elements as an iterator. The split_off method splits the vector
at an index and returns the second part as a new vector.
let small: Vec<i32> = data.extract_if(.., |x| *x < 4).collect();
The extract_if method removes the elements that match the
closure and returns them; the rest stay in the vector. It combines
retain with collecting the removed elements.
$ cargo run -q dedup: [1, 2, 3, 4, 5, 6] retain: [2, 4, 6] ["sky", "rock", "sun"] drained: [3, 4, 5], left: [1, 2, 6, 7, 8, 9, 10] [1, 2, 6, 7] [8, 9, 10] [1, 1, 2] [5, 4, 5, 9, 6]
Iterating over vectors
A vector can be iterated over by shared references, by mutable references, or by value. Iterating by value consumes the vector.
fn main() {
let mut numbers = vec![1, 2, 3, 4, 5];
for n in &numbers {
print!("{n} ");
}
println!();
for n in &mut numbers {
*n *= 2;
}
println!("{numbers:?}");
for (i, n) in numbers.iter().enumerate() {
print!("{i}:{n} ");
}
println!();
let strings = vec![String::from("Hello"), String::from("World")];
for s in strings {
println!("consumed: {s}");
}
}
We go over the elements in the three ways.
for n in &numbers {
print!("{n} ");
}
Iterating over &numbers borrows the vector; the loop variable
is a &i32. The vector can be used after the loop.
for n in &mut numbers {
*n *= 2;
}
Iterating over &mut numbers gives mutable references, through
which we change the elements.
for (i, n) in numbers.iter().enumerate() {
The enumerate adapter adds the index to each element.
for s in strings {
println!("consumed: {s}");
}
Without a reference, the loop takes ownership of the vector and moves the
strings out of it. The strings variable cannot be used after the
loop.
$ cargo run -q 1 2 3 4 5 [2, 4, 6, 8, 10] 0:2 1:4 2:6 3:8 4:10 consumed: Hello consumed: World
Borrowing rules
While a reference to an element exists, the vector cannot be modified. A modification may reallocate the buffer, which would leave the reference pointing to freed memory.
fn main() {
let mut vals = vec![1, 2, 3];
let first = &vals[0];
vals.push(4);
println!("{first}");
}
We take a reference to the first element and then push a new element.
let first = &vals[0];
vals.push(4);
println!("{first}");
The push method needs a mutable borrow of the vector, but the
shared borrow in first is still used later. The compiler reports
the error E0502. Moving the println! before the
push, or copying the value with let first = vals[0];,
fixes the code.
$ cargo run -q
error[E0502]: cannot borrow `vals` as mutable because it is also borrowed as immutable
--> src/main.rs:5:5
|
4 | let first = &vals[0];
| ---- immutable borrow occurs here
5 | vals.push(4);
| ^^^^^^^^^^^^ mutable borrow occurs here
6 |
7 | println!("{first}");
| ----- immutable borrow later used here
For more information about this error, try `rustc --explain E0502`.
Capacity and length
The length is the number of elements; the capacity is the number of elements that fit into the allocated buffer.
fn main() {
let mut v = Vec::with_capacity(3);
println!("initial: len {}, cap {}", v.len(), v.capacity());
v.push(1);
v.push(2);
v.push(3);
println!("full: len {}, cap {}", v.len(), v.capacity());
v.push(4);
println!("grown: len {}, cap {}", v.len(), v.capacity());
v.shrink_to_fit();
println!("shrunk: len {}, cap {}", v.len(), v.capacity());
v.reserve(10);
println!("reserved: len {}, cap {}", v.len(), v.capacity());
let mut w = Vec::new();
let mut caps = vec![w.capacity()];
for i in 0..100 {
w.push(i);
if w.capacity() != *caps.last().unwrap() {
caps.push(w.capacity());
}
}
println!("{caps:?}");
}
We watch how the capacity changes when the vector grows.
v.push(4);
println!("grown: len {}, cap {}", v.len(), v.capacity());
The fourth element does not fit into the buffer, so the vector reallocates. The new capacity is twice the old one.
v.shrink_to_fit(); v.reserve(10);
The shrink_to_fit method reduces the capacity to the length;
reserve makes room for at least ten more elements.
let mut w = Vec::new();
let mut caps = vec![w.capacity()];
for i in 0..100 {
w.push(i);
if w.capacity() != *caps.last().unwrap() {
caps.push(w.capacity());
}
}
We record the capacity each time it changes. For elements of this size, the
first allocation has room for four elements, and then the capacity doubles.
Doubling makes push fast on average: over a hundred pushes, the
vector allocates a buffer only six times. The exact growth strategy is not guaranteed and
may change.
$ cargo run -q initial: len 0, cap 3 full: len 3, cap 3 grown: len 4, cap 6 shrunk: len 4, cap 4 reserved: len 4, cap 14 [0, 4, 8, 16, 32, 64, 128]
Slices
A slice, &[T], is a view into a contiguous part of a vector
or an array. Slices are created with ranges and do not copy the data.
fn sum(vals: &[i32]) -> i32 {
vals.iter().sum()
}
fn main() {
let data = vec![10, 20, 30, 40, 50, 60];
let first_half = &data[..3];
let middle = &data[1..4];
let last = &data[4..];
println!("{first_half:?} {middle:?} {last:?}");
println!("sum of all: {}", sum(&data));
println!("sum of a part: {}", sum(&data[2..5]));
println!("sum of an array: {}", sum(&[1, 2, 3]));
for chunk in data.chunks(4) {
println!("chunk: {chunk:?}");
}
let diffs: Vec<i32> = data.windows(2).map(|w| w[1] - w[0]).collect();
println!("diffs: {diffs:?}");
let (left, right) = data.split_at(2);
println!("{left:?} {right:?}");
}
We create slices of a vector and pass them to a function.
fn sum(vals: &[i32]) -> i32 {
vals.iter().sum()
}
A function that reads a sequence should take a slice instead of
&Vec<T>. Then it accepts a whole vector, a part of it,
and an array as well. A &Vec<i32> is converted to
&[i32] automatically.
for chunk in data.chunks(4) {
println!("chunk: {chunk:?}");
}
The chunks method splits the slice into parts of the given size;
the last part may be shorter.
let diffs: Vec<i32> = data.windows(2).map(|w| w[1] - w[0]).collect();
The windows method returns overlapping slices. We compute the
differences between neighbouring elements. See the
Rust slices article for more slice methods.
$ cargo run -q [10, 20, 30] [20, 30, 40] [50, 60] sum of all: 210 sum of a part: 120 sum of an array: 6 chunk: [10, 20, 30, 40] chunk: [50, 60] diffs: [10, 10, 10, 10, 10] [10, 20] [30, 40, 50, 60]
Sorting and searching
Vectors are sorted in place with sort and
sort_by. A sorted vector can be searched with
binary_search.
fn main() {
let mut nums = vec![42, 7, 19, 3, 99, 15];
nums.sort();
println!("sorted: {nums:?}");
match nums.binary_search(&19) {
Ok(idx) => println!("found 19 at index {idx}"),
Err(_) => println!("19 not found"),
}
if let Err(idx) = nums.binary_search(&20) {
nums.insert(idx, 20);
}
println!("with 20: {nums:?}");
nums.sort_by(|a, b| b.cmp(a));
println!("descending: {nums:?}");
println!("contains 42? {}", nums.contains(&42));
println!("position of 7: {:?}", nums.iter().position(|&x| x == 7));
let mut temps: Vec<f64> = vec![22.5, -3.1, 17.0, 8.4];
temps.sort_by(|a, b| a.total_cmp(b));
println!("{temps:?}");
}
We sort numbers, search them, and keep the vector sorted when inserting.
match nums.binary_search(&19) {
Ok(idx) => println!("found 19 at index {idx}"),
Err(_) => println!("19 not found"),
}
Binary search works only on sorted data. It returns Ok with the
index of the found element.
if let Err(idx) = nums.binary_search(&20) {
nums.insert(idx, 20);
}
For a missing value, binary_search returns Err with
the position where the value can be inserted to keep the order.
nums.sort_by(|a, b| b.cmp(a));
The sort_by method takes a comparison function. Swapping the
arguments sorts in descending order. The contains and
position methods search linearly and work on unsorted data.
let mut temps: Vec<f64> = vec![22.5, -3.1, 17.0, 8.4]; temps.sort_by(|a, b| a.total_cmp(b));
Floats do not implement Ord, because NaN is not
comparable, so sort is not available. The
total_cmp method defines a total order for floats.
$ cargo run -q sorted: [3, 7, 15, 19, 42, 99] found 19 at index 3 with 20: [3, 7, 15, 19, 20, 42, 99] descending: [99, 42, 20, 19, 15, 7, 3] contains 42? true position of 7: Some(5) [-3.1, 8.4, 17.0, 22.5]
Sorting structures
Vectors of structures are sorted by a key or with a custom comparison.
#[derive(Debug)]
struct User {
name: String,
age: u32,
}
fn main() {
let mut users = vec![
User { name: String::from("Paul"), age: 33 },
User { name: String::from("Anna"), age: 24 },
User { name: String::from("Robert"), age: 33 },
User { name: String::from("Lucy"), age: 19 },
];
users.sort_by_key(|u| u.age);
for u in &users {
println!("{} {}", u.name, u.age);
}
println!();
users.sort_by(|a, b| b.age.cmp(&a.age).then_with(|| a.name.cmp(&b.name)));
for u in &users {
println!("{} {}", u.name, u.age);
}
let oldest = users.iter().max_by_key(|u| u.age).unwrap();
println!("{oldest:?}");
}
We sort users by age and then by age in descending order and by name.
users.sort_by_key(|u| u.age);
The sort_by_key method sorts by the value returned by the
closure. The sort is stable: Paul and Robert have the same age and keep their
original order.
users.sort_by(|a, b| b.age.cmp(&a.age).then_with(|| a.name.cmp(&b.name)));
The then_with method of Ordering adds a secondary
key: users with the same age are sorted by name.
let oldest = users.iter().max_by_key(|u| u.age).unwrap();
When several elements have the maximum key, max_by_key returns
the last of them, here Robert.
$ cargo run -q
Lucy 19
Anna 24
Paul 33
Robert 33
Paul 33
Robert 33
Anna 24
Lucy 19
User { name: "Robert", age: 33 }
Transforming vectors
Iterator methods like map, filter, and
collect create new vectors from existing ones.
fn main() {
let numbers: Vec<i32> = (1..=10).collect();
let even_squares: Vec<i32> = numbers
.iter()
.filter(|&x| x % 2 == 0)
.map(|x| x * x)
.collect();
println!("{even_squares:?}");
let labels: Vec<String> = numbers.iter().take(3).map(|n| format!("#{n}")).collect();
println!("{labels:?}");
let (even, odd): (Vec<i32>, Vec<i32>) = numbers.iter().partition(|&x| x % 2 == 0);
println!("{even:?} {odd:?}");
let total: i32 = numbers.iter().sum();
let max = numbers.iter().max();
let avg = total as f64 / numbers.len() as f64;
println!("sum {total}, max {max:?}, average {avg}");
let words: Vec<String> = numbers.iter().take(4).map(|n| n.to_string()).collect();
println!("{}", words.join(", "));
println!("{:?}", [vec![1, 2], vec![3], vec![4, 5]].concat());
}
We transform and aggregate a vector of numbers.
let even_squares: Vec<i32> = numbers
.iter()
.filter(|&x| x % 2 == 0)
.map(|x| x * x)
.collect();
We keep the even numbers and square them. The iterator chain is compiled into a simple loop; no intermediate vectors are created.
let (even, odd): (Vec<i32>, Vec<i32>) = numbers.iter().partition(|&x| x % 2 == 0);
The partition method splits the elements into two vectors.
let total: i32 = numbers.iter().sum(); let max = numbers.iter().max();
The sum method needs a type annotation. The max
method returns an Option, because an empty vector has no
maximum.
println!("{}", words.join(", "));
println!("{:?}", [vec![1, 2], vec![3], vec![4, 5]].concat());
The join method joins strings with a separator;
concat joins vectors into one.
$ cargo run -q [4, 16, 36, 64, 100] ["#1", "#2", "#3"] [2, 4, 6, 8, 10] [1, 3, 5, 7, 9] sum 55, max Some(10), average 5.5 1, 2, 3, 4 [1, 2, 3, 4, 5]
Vectors of vectors
A vector of vectors represents a two-dimensional grid, whose rows can have different lengths.
fn main() {
let rows = 3;
let cols = 4;
let mut grid = vec![vec![0; cols]; rows];
for (r, row) in grid.iter_mut().enumerate() {
for (c, cell) in row.iter_mut().enumerate() {
*cell = r * cols + c;
}
}
for row in &grid {
println!("{row:?}");
}
println!("grid[1][2] = {}", grid[1][2]);
let col_sums: Vec<usize> = (0..cols).map(|c| grid.iter().map(|row| row[c]).sum()).collect();
println!("column sums: {col_sums:?}");
let flat: Vec<usize> = grid.into_iter().flatten().collect();
println!("{flat:?}");
}
We create a grid of three rows and four columns and fill it with numbers.
let mut grid = vec![vec![0; cols]; rows];
The inner vector is cloned for each row. Each row is a separate heap allocation.
for (r, row) in grid.iter_mut().enumerate() {
for (c, cell) in row.iter_mut().enumerate() {
*cell = r * cols + c;
}
}
Nested loops with iter_mut modify the cells.
let col_sums: Vec<usize> = (0..cols).map(|c| grid.iter().map(|row| row[c]).sum()).collect();
To sum a column, we take the element with the same index from every row.
let flat: Vec<usize> = grid.into_iter().flatten().collect();
The flatten adapter joins the rows into a single vector. For
large grids of a fixed size, a single vector with r * cols + c
indexing is more efficient.
$ cargo run -q [0, 1, 2, 3] [4, 5, 6, 7] [8, 9, 10, 11] grid[1][2] = 6 column sums: [12, 15, 18, 21] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Comparing vectors
Vectors can be compared with the comparison operators if their elements can be compared.
fn main() {
let a = vec![1, 2, 3];
let b = vec![1, 2, 3];
let c = vec![1, 2, 4];
println!("{}", a == b);
println!("{}", a == [1, 2, 3]);
println!("{}", a < c);
println!("{}", vec![1, 2] < vec![1, 2, 0]);
let mut copy = a.clone();
copy.push(4);
println!("{a:?} {copy:?}");
println!("{}", a.starts_with(&[1, 2]));
println!("{}", copy.ends_with(&[3, 4]));
println!("{}", a.is_empty());
}
We compare vectors and check their beginnings and ends.
println!("{}", a == b);
println!("{}", a == [1, 2, 3]);
Two vectors are equal if they have the same elements in the same order. A vector can also be compared with an array.
println!("{}", a < c);
println!("{}", vec![1, 2] < vec![1, 2, 0]);
The comparison is lexicographic: the first differing element decides; a shorter vector that is a prefix of a longer one is smaller.
let mut copy = a.clone(); copy.push(4);
The clone method creates an independent copy with its own
buffer.
$ cargo run -q true true true true [1, 2, 3] [1, 2, 3, 4] true true false
Source
The Rust Programming Language: Storing Lists of Values with Vectors
In this article we have worked with vectors in Rust.
Author
List all Rust tutorials.