Тип Slice представляет часть набора элементов, например, часть массива.
Формальное определение slice:
let slice = &набор_элементов[начальный_индекс..конечный_индекс];
Для извлечения набора элементов применяется синтаксис последовательностей - оператор .., слева от которого указывается начальный индекс, а справа - конечный индекс.
При этом слайс определяется как ссылка, поэтому он не владеет полученным поднабором элементов, а лишь содержит ссылку на этот поднабор.
Например, определим slice, который представляет часть массива:
fn main(){ let numbers = [1, 2, 3, 4, 5, 6, 7, 8]; let slice = &numbers[1..5]; // получим слайс println!("slice[0]={}", slice[0]); // выведем первый элемент слайса // перебор слайса for num in slice{ print!("{} ", num) // 2 3 4 5 } }
Выражение numbers[1..5]
указывает, что мы хотим взять из массива элементы, начиная с 1-го индекса по 5-й.
Так как индексация в массиве начинается с нуля, а конечный индекс в результат не включается, то из массива [1, 2, 3, 4, 5, 6, 7, 8]
мы получим подмассив [2, 3, 4, 5]
.
После инициализации слайса можно обращаться к его элементам. Например, как в массиве по индексу:
println!("slice[0]={}", slice[0]); // выведем первый элемент слайса
Также можно перебрать элементы в цикле for
.
Консольный вывод программы:
slice[0]=2 2 3 4 5
Если надо взять элементы, начиная с индекса 0, то его можно не указывать. Также можно не указывать конечный индекс, если необходимо взять элементы вплоть до последнего. Таким образом, можно применять следующие комбинации:
numbers[..]
эквивалентно [1, 2, 3, 4, 5, 6, 7, 8]
numbers[..3]
эквивалентно [1, 2, 3 ]
numbers[..=3]
эквивалентно [1, 2, 3, 4]
numbers[1..]
эквивалентно [2, 3, 4, 5, 6, 7, 8]
numbers[1..3]
эквивалентно [2, 3]
numbers[1..=3]
эквивалентно [2, 3, 4]
Также через слайс можно изменять элементы поднабора (и соответственно начального набора). В этом случае слайс должен быть определен как изменяемая ссылка с оператором &mut:
fn main(){ let mut numbers = [1, 2, 3, 4, 5, 6, 7, 8]; let slice = &mut numbers[1..5]; // получим слайс // изменим первый элемент слайса slice[0] = 81; println!("slice[0]={}", slice[0]); // slice[0]=81 // перебор измененного слайса for num in slice{ print!("{} ", num) // 81 3 4 5 } println!(); // перебор начального массива for num in numbers{ print!("{} ", num) // 1 81 3 4 5 6 7 8 } }
Подобным образом можно получить поднабор и из других наборов элементов, например, из строки - типа String:
fn main(){ let message = "hello world!"; let slice = &message[..5]; // часть с строки с начала до 6 символа println!("slice={}", slice); // hello println!("message={}", message); // hello world! }
Стоит отметить, что для представления строкового слайса в Rust есть специальный тип - &str, который уже ранее использовался в предыдущих статьях. То есть в данном случае мы могли бы написать:
fn main(){ let message = "hello world!"; let slice: &str = &message[..5]; // часть с строки с начала до 6 символа println!("slice={}", slice); // hello println!("message={}", message); // hello world! }
Поэтому когда мы присваивали переменной обычную строку:
let hello = "hello world";
Фактически здесь переменная hello
представляла строковый слайс или тип &str
.