Коллекции

Вектор

Последнее обновление: 28.04.2021

Для хранения набора однотипных данных в языке Rust предназначены массивы. Однако они имеют недостаток - после их определения мы не можем изменить их длину, не можем ни добавить новый элемент, ни удалить уже существующий. Этот недостаток призван устранить вектор, который представлен типом Vec<T> (а точнее структурой std::vec::Vec<T>). Вектор как раз и представляет динамически изменяемый набор однотипных данных.

Определение вектора

Есть разные способы определения вектора. Первый способ - вызов функции Vec::new(), которая создает пустой вектор:

let v: Vec<тип_данных> = Vec::new();

Например:

let v: Vec<i32> = Vec::new();

В данной случае также указан тип вектора - Vec<i32> - то есть вектор, который хранит значения типа i32.

Второй способ представляет применение специального макроса vec!, после которого в квадратных скобках через запятую перечисляются элементы вектора:

let v = vec! [значение1, значени2, ... значениеN];

Например:

let v = vec![1, 2, 3];

Здесь для вектора определены три элемента типа i32, поэтому вектор неявно будет иметь тип Vec<i32>

При этом вектор может быть и пустым:

let v: Vec<i32>= vec![];

Третий способ представляет заполнение вектора значениями по умолчанию:

let v = vec![val; repeat];

В квадратных скобках после макроса vec! указываются два значения. Первое значение указывает на значение по умолчанию, которым заполняется вектор, а второе значение - начальное количество элементов. Например:

let v = vec![5; 3];

Этот вектор будет аналогичен следущему:

let v = vec![5, 5, 5];

Добавление элементов

Для добавления элементов в вектор применяется метод push():

let mut users = Vec::new();
users.push("Tom");
users.push("Sam");
users.push("Bob");

Причем если предполагается изменение вектора, то его переменная должна быть определена с помощью оператора mut.

При это в примере выше указан тип вектора, так как Rust на основе добавляемых значений может определить тип. Однако все добавляемые значения, должны иметь один и тот же тип данных.

Обращение к элементам вектора

Обращение к элементам вектора производится так же, как и к элементам массива с помощью индексов:

вектор[индекс_элемента]

Например, получим и изменим некоторые элементы вектора:

fn main(){
  
    let mut users = vec!["Tom", "Sam", "Bob"];
	
	println!("1. {}", users[0]);	// Tom
	println!("2. {}", users[1]);	// Sam
	println!("3. {}", users[2]);	// Bob
	
	// меняем значение элемента
	users[1] = "Alice";
	println!("После изменения: 2. {}", users[1]);	// Alice
}

Консольный вывод:

1. Tom
2. Sam
3. Bob
После изменения: 2. Alice

Перебор вектора

Для перебора вектора можно использовать цикл for:

fn main(){
  
    let users = vec!["Tom", "Sam", "Bob"];

	for user in &users{
		println!("{}", user);
	}
}

Обратите внимания, что циклу for передается не сам объект вектора users, а ссылка на него. Дело в том, что передача объекта в цикл меняет владение вектора. После чего мы не сможем ссылаться на этот вектор через переменную users. Проблему можно увидеть на следующем примере:

fn main(){
  
    let mut users = vec!["Tom", "Sam", "Bob"];

	for user in users{
		print!("{} ", user);
	}
	users.push("Alice");	// ! Ошибка - переменнаяя users более недействительна
}

Здесь в цикл передается не ссылка, а полноценный объект вектора. В итоге владение вектором перемещается от переменной users в цикл for. Поэтому на строке

users.push("Alice");

при компиляции мы получим ошибку, так как переменная users больше не представляет объект вектора.

Длина вектора

Длина вектора возвращается методом len():

fn main(){
  
    let mut users = vec!["Tom", "Sam", "Bob"];
	println!("length: {}", users.len());	// 3
}

Удаление элементов

Для удаления элемента по индексу применяется метод remove():

fn main(){
  
    let mut users = vec!["Tom", "Sam", "Bob", "Alice"];
	let removed_element = users.remove(1);	 // удаляем второй элемент
	
	println!("Удаленный элемент: {}", removed_element);	// Sam
	for user in &users{
		print!("{} ", user);	// Tom Bob Alice
	}
}

Еще один метод - pop() удаляет элемент из конца вектора и возвращает его:

fn main(){
  
    let mut users = vec!["Tom", "Sam", "Bob", "Alice"];
	let removed_element = users.pop();	 // удаляем элемент из конца
	
	println!("Удаленный элемент: {}", removed_element.unwrap());	// Alice
	for user in &users{
		print!("{} ", user);	// Tom Sam Bob
	}
}

В реальности метод pop() возвращает объект перечисления Option<T>. И чтобы получить из него содержащийся в нем элемент, применяется метод unwrap(): removed_element.unwrap().

Это только часть функционала векторов. Все методы вектора можно посмотреть в документации - https://doc.rust-lang.org/std/vec/struct.Vec.html

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850