Rust Slice Operations: Mastering Subsequence Extraction
Slices are a fundamental and powerful feature in Rust for working with contiguous sequences of elements. They provide a flexible way to borrow and manipulate parts of collections without needing to copy data. This challenge will test your understanding of how to create and utilize slices effectively for various subsequence extraction tasks.
Problem Description
Your task is to implement functions that perform common slice operations. Specifically, you will need to create functions that:
- Extract a sub-slice: Given a slice and a range, return a new slice representing the elements within that range.
- Filter a slice: Given a slice and a predicate function, return a new
Veccontaining only the elements that satisfy the predicate. - Find the first occurrence: Given a slice and a target element, return an
Option<&T>representing a reference to the first occurrence of the target element, orNoneif it's not found.
You should aim for efficient solutions that leverage Rust's borrowing and slicing mechanisms.
Examples
Example 1: Extracting a Sub-slice
Input:
data: &[i32] = &[1, 2, 3, 4, 5]
range: std::ops::Range<usize> = 1..4
Output:
&[i32] = &[2, 3, 4]
Explanation:
The function takes the original slice [1, 2, 3, 4, 5] and the range 1..4. It returns a new slice containing elements from index 1 (inclusive) up to index 4 (exclusive), which are 2, 3, and 4.
Example 2: Filtering a Slice
Input:
data: &[i32] = &[1, 2, 3, 4, 5, 6]
predicate: |&x| x % 2 == 0 (a closure that checks if a number is even)
Output:
Vec<i32> = vec![2, 4, 6]
Explanation:
The function iterates through the slice [1, 2, 3, 4, 5, 6]. The predicate |&x| x % 2 == 0 is applied to each element. Only the elements for which the predicate returns true (i.e., the even numbers) are collected into a new Vec.
Example 3: Finding the First Occurrence
Input:
data: &[char] = &['a', 'b', 'c', 'b', 'd']
target: char = 'b'
Output:
Option<&char> = Some(&'b')
Explanation:
The function searches the slice ['a', 'b', 'c', 'b', 'd'] for the character 'b'. It finds the first occurrence at index 1 and returns a reference to that character wrapped in Some.
Example 4: Finding the First Occurrence (Not Found)
Input:
data: &[char] = &['a', 'b', 'c', 'b', 'd']
target: char = 'z'
Output:
Option<&char> = None
Explanation:
The function searches the slice ['a', 'b', 'c', 'b', 'd'] for the character 'z'. Since 'z' is not present in the slice, it returns None.
Constraints
- The input slices can contain elements of any type
Tthat implementsCloneandPartialEqwhere applicable (for filtering and searching). - The ranges for sub-slice extraction will be valid and within the bounds of the input slice.
- The predicate function for filtering will always accept a reference to an element of type
Tand return abool. - The target element for searching will be of type
T. - Consider the efficiency: your solutions should not unnecessarily copy data.
Notes
- Familiarize yourself with Rust's slicing syntax (e.g.,
&[T][start..end]). - The
std::ops::Rangestruct is commonly used for specifying ranges. - The
Iteratortrait and its methods (likefilter,collect,find) will be very useful for the filtering and searching operations. - Pay attention to the return types of your functions, especially the use of
Optionfor potentially absent values.