RustArena

Step 4 of 6

Array and Vec slices: &[T]

Slices aren't only for text. &v[1..3] is a slice of a vector or array: its type is &[T] (for example &[i32]), a pointer to the first element plus a count of elements.

fn main() {
    let temps = vec![14, 17, 21, 19, 16, 12, 10];
    let weekdays = &temps[..5];
    let weekend = &temps[5..];
    println!("weekdays {:?}, weekend {:?}", weekdays, weekend);
    println!("{} + {} days", weekdays.len(), weekend.len());
}
weekdays [14, 17, 21, 19, 16], weekend [12, 10]
5 + 2 days
 temps: Vec<i32>  ┌────────────┐
                  │ ptr ───────┼───────►  [14, 17, 21, 19, 16, 12, 10]   (heap)
                  │ len 7      │           ▲                   ▲
                  │ cap 7      │           │                   │
                  └────────────┘           │                   │
 weekdays: &[i32] ┌────────────┐           │                   │
                  │ ptr ───────┼───────────┘                   │
                  │ len 5      │                               │
                  └────────────┘                               │
 weekend: &[i32]  ┌────────────┐                               │
                  │ ptr ───────┼───────────────────────────────┘
                  │ len 2      │
                  └────────────┘

Functions that take &[T]

A &[T] parameter accepts a vector, an array, or any part of either. A &Vec<T> turns into a &[T] automatically, just like &String turns into &str:

fn total(values: &[i32]) -> i32 {
    let mut sum = 0;
    for v in values {
        sum += v;
    }
    sum
}

fn main() {
    let week = vec![3, 5, 2, 8, 6, 1, 0];
    let fixed = [10, 20, 30];
    println!("{}", total(&week));         // &Vec<i32> becomes &[i32]
    println!("{}", total(&week[..5]));    // part of it
    println!("{}", total(&fixed));        // an array
    println!("{}", total(&[]));           // an empty slice
}
25
24
60
0

Workplace note: it's the same advice as for text: prefer &[T] over &Vec<T> for parameters (clippy's ptr_arg lint again). &str is to String what &[T] is to Vec<T>: a borrowed view that doesn't care who owns the data.

What you can do with a &[T]:

fn main() {
    let scores = [88, 92, 75, 64, 99, 81];
    let (first_half, second_half) = scores.split_at(3);
    println!("{:?} | {:?}", first_half, second_half);
    println!("has a 99: {}", scores.contains(&99));
}
[88, 92, 75] | [64, 99, 81]
has a 99: true

Common mistakes

Your task

Write average, which returns the average of a slice of f64s, or 0.0 for an empty slice. The tests call it with a vector, an array and part of a vector.

Challenge 2

Write count_above, which returns how many values in the slice are greater than limit. The tests call it with a vector, an array and part of a vector.

Challenge 3

Write total(values: &[i32]) -> i32 and use it to finish main: split the numbers into two halves (the first half gets numbers.len() / 2 elements, so the second half gets the extra one for odd counts) and print each half with its total. For the input 3 5 2 8 6 it prints:

first half [3, 5]: 8
second half [2, 8, 6]: 16

Previous: Returning slices: first_word Next: Mutable slices: &mut [T]