[Avg. reading time: 5 minutes]
Slices
Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection. A slice is a kind of reference, so it does not have ownership.
A string slice is a reference to part of a String, and it looks like this:
- A slice is a borrowed view into data.
- It does not own the data.
- It prevents copying large data unnecessarily.
- Array slice → &[T]
- String slice → &str
Example 1
// String Slicing fn main() { //define an array of size 4 let arr:[i32;7] = [1, 2, 3, 4,5,6,7]; //define the slice let slice_array1 = &arr; let slice_array2 = &arr[0..4]; let slice_array3 = &arr[3..]; // print the slice of an array println!("Value of slice_array1: {:?}", slice_array1); println!("Value of slice_array2: {:?}", slice_array2); println!("Value of slice_array3: {:?}", slice_array3); }
start..end -> includes start, excludes end
..end -> from beginning to end
start.. > from start to end
.. -> whole collection
A slice is just a reference. The original array still owns the data.
Example 2
fn first_word(s: &str) -> &str { let bytes = s.as_bytes(); for (i, &b) in bytes.iter().enumerate() { if b == b' ' { return &s[..i]; } } &s[..] } fn main() { let s = String::from("hello world"); let word = first_word(&s); println!("{}", word); }
Why convert to bytes?
- Rust strings are UTF-8.
- Some characters take more than 1 byte.
- We search for a space ’ ’ which is a single byte.
- So we scan bytes safely.
- We are not slicing randomly.
- We slice exactly at the byte where the space exists.
If you try slicing in the middle of a multi-byte character, Rust will panic.