В этой статье мы подробно рассмотрим векторы Rust, мощную и гибкую структуру данных для работы с массивами с изменяемым размером. На примерах, начиная от базовых и заканчивая продвинутыми, мы стремимся помочь вам получить полное представление об этой важной функции Rust.
Что такое векторы?
Векторы в Rust аналогичны динамическим массивам или ArrayList
на других языках. Они могут расти или уменьшаться в размере и хранить элементы одного типа. Векторы являются частью стандартной библиотеки Rust и представлены типом Vec<T>
, где T
- тип элементов в векторе.
Создание векторов
Создание вектора в Rust несложно. Можно создать пустой вектор или инициализировать его с помощью элементов.
// Создание пустого вектора
let mut numbers: Vec<i32> = Vec::new();
// Создание вектора с элементами
let numbers = vec![1, 2, 3, 4, 5];
Емкость и перераспределение
Векторы в Rust хранят свои элементы в куче. Они имеют емкость, которая указывает объем пространства, выделенного для элементов. При добавлении элементов к вектору и превышении его емкости Rust автоматически увеличивает вектор, перераспределяя память, удваивая емкость каждый раз.
let mut numbers = Vec::with_capacity(2);
numbers.push(1);
numbers.push(2);
println!("Вместительность: {}", numbers.capacity()); // Вместительность: 2
// Эта операция инициирует перераспределение
numbers.push(3);
println!("Вместительность: {}", numbers.capacity()); // Вместительность: 4
Добавление и удаление элементов
Можно легко добавлять и удалять элементы из вектора с помощью методов push
, pop
, insert
и remove
.
let mut numbers = vec![1, 2, 3];
numbers.push(4);
numbers.push(5);
println!("{:?}", numbers); // [1, 2, 3, 4, 5]
let last = numbers.pop();
println!("Удаленный: {:?}", last); // Удаленный: Some(5)
println!("{:?}", numbers); // [1, 2, 3, 4]
numbers.insert(1, 42);
println!("{:?}", numbers); // [1, 42, 2, 3, 4]
let removed = numbers.remove(1);
println!("Удаленный: {}", removed); // Удаленный: 42
println!("{:?}", numbers); // [1, 2, 3, 4]
Доступ к элементам и их изменение
Доступ к элементам вектора можно осуществлять с помощью индекса метода get
или сопоставления шаблонов. Модификация элементов также возможна с изменяемыми ссылками.
let mut numbers = vec![1, 2, 3, 4, 5];
// Доступ к элементам по индексу
println!("Первый элемент: {}", numbers[0]); // Первый элемент: 1
// Доступ к элементам с помощью метода `get`
let third = numbers.get(2);
println!("Третий элемент: {:?}", third); // Третий элемент: Some(3)
match numbers.get(2) {
Some(val) => println!("Третий элемент: {}", val),
None => println!("Элемент не найден"),
}
//Изменение элементов
numbers[1] = 42;
println!("{:?}", numbers); // [1, 42, 3, 4, 5]
Итерация по вектору
Можно выполнить итерацию по вектору с помощью цикла for
, который позволяет выполнять операции над каждым элементом.
let numbers = vec![1,2, 3, 4, 5];
// Итерация по векторным элементам
for num in &numbers {
println!("Number: {}", num);
}
// Итерация по изменяемым ссылкам для изменения векторных элементов
let mut numbers = vec![1, 2, 3, 4, 5];
for num in &mut numbers {
*num *= 2;
}
println!("{:?}", numbers); // [2, 4, 6, 8, 10]
Срез векторов
Фрагментирование элементов допускается в векторе. Для создания фрагмента можно использовать синтаксис диапазона.
let numbers = vec![1, 2, 3, 4, 5];
// Создание фрагмента из индекса 1 (включительно) в 4 (эксклюзивно)
let slice = &numbers[1..4];
println!("{:?}", slice); // [2, 3, 4]
Помните, что синтаксис диапазона является полуоткрытым, что означает, что конечный индекс является эксклюзивным. Если требуется включить последний элемент, необходимо использовать диапазон 1..=4
.
Создание векторов из итераторов
Можно создать вектор из любого итератора, который вырабатывает элементы одного типа с помощью метода collect
.
// Создание вектора квадратных чисел
let numbers = vec![1, 2, 3, 4, 5];
let squared: Vec<i32> = numbers.iter().map(|n| n * n).collect();
println!("{:?}", squared); // [1, 4, 9, 16, 25]
Дополнительные операции с вектором
Существует много других полезных методов, доступных для векторов, таких как len
, is_empty
, contains
, retain
, sort
и concat
. Полный список можно найти в официальной документации по Rust.
К настоящему времени у вас должно сложиться четкое понимание векторов Rust и способов эффективной работы с ними. От создания и изменения векторов до итерации и разрезания, эти мощные структуры данных предлагают широкий спектр возможностей для управления динамическими массивами в Rust.