// When performing operations on elements within a collection, iterators are// essential. This module helps you get familiar with the structure of using an// iterator and how to go through elements within an iterable collection.fnmain(){// You can optionally experiment here.}#[cfg(test)]mod tests {#[test]fniterators(){letmy_fav_fruits=["banana","custard apple","avocado","peach","raspberry"];// Create an iterator over the array.letmutfav_fruits_iterator=my_fav_fruits.iter();assert_eq!(fav_fruits_iterator.next(),Some(&"banana"));assert_eq!(fav_fruits_iterator.next(),Some(&"custard apple"));// Replace `todo!()`assert_eq!(fav_fruits_iterator.next(),Some(&"avocado"));assert_eq!(fav_fruits_iterator.next(),Some(&"peach"));// Replace `todo!()`assert_eq!(fav_fruits_iterator.next(),Some(&"raspberry"));assert_eq!(fav_fruits_iterator.next(),None);// Replace `todo!()`}}
This exercise is simple we just need to create iterators based on my_fav_fruits array.
We can do this by calling iter method like this:
iterators2.rs
First task in this exercise is to complete the capitalize_first function.
We already have match syntax for first char for the given input.
We just need to uppercase it and combine it with the reset of the chars.
We can do it by using format or + like this:
or
Second and third task is kinda similar, in here we will learn how powerful method collect is.
In the capitalize_words_vector function we need to iterate given words and capitalize it using function in the first task.
We can do it like this:
collect() can take anything iterable, and turn it into a relevant collection.
In this case rust will convert the iterator to desired return type which is Vec<String>.
This also means that we can use the same code for our next task in function capitalize_words_string and Rust will convert the iterator into desired return type which is String.
iterators3.rs
First task in this exercise is to complete the function divide to return error in accordance with enum DivisionError.
For the overflow checking we can do it by using method overflowing_div.
Second task is to fix function result_with_list.
The return signature that satisfy the desired output should be Result<Vec<i64>, DivisionError>.
And we can use into_iter().collect() method chain to convert the iterator to the desired output.
Similar like previous task, the last task is to fix function list_of_results.
The return signature that satisfy the desired output should be Vec<Result<i64, DivisionError>>.
And we can use into_iter().collect() method chain to convert the iterator to the desired output.
iterators4.rs
This exercise is straightforward, we just need to finish the factorial function.
We can use fold method to do this.
Folds every element into an accumulator by applying an operation, returning the final result.
But then you will see in that rust compiler will suggest to use product instead like this:
Iterates over the entire iterator, multiplying all the elements
iterators5.rs
This exercise may looks intimidating but its quite simple.
First is we need to complete the function count_iterator.
Basically we need to return count of given hashmap values that match with given Progress.
We can use iterator, map it, then calculate the sum like this:
Second is we need to complete the function count_collection_iterator.
Basically for each hashmap in the given collection we need to count it the matching progress and sum it.
Similar like the first task we can iter, map, then sum it like this:
#[derive(Debug, PartialEq, Eq)]
enum DivisionError {
// Example: 42 / 0
DivideByZero,
// Only case for `i64`: `i64::MIN / -1` because the result is `i64::MAX + 1`
IntegerOverflow,
// Example: 5 / 2 = 2.5
NotDivisible,
}
// Calculate `a` divided by `b` if `a` is evenly divisible by `b`.
// Otherwise, return a suitable error.
fn divide(a: i64, b: i64) -> Result<i64, DivisionError> {
if b == 0 {
return Err(DivisionError::DivideByZero);
}
let (r, overflow) = a.overflowing_div(b);
if overflow {
return Err(DivisionError::IntegerOverflow);
}
if a % b != 0 {
return Err(DivisionError::NotDivisible);
}
Ok(r)
}
// Add the correct return type and complete the function body.
// Desired output: `Ok([1, 11, 1426, 3])`
fn result_with_list() -> Result<Vec<i64>, DivisionError> {
let numbers = [27, 297, 38502, 81];
let division_results = numbers.into_iter().map(|n| divide(n, 27));
division_results.into_iter().collect()
}
// Add the correct return type and complete the function body.
// Desired output: `[Ok(1), Ok(11), Ok(1426), Ok(3)]`
fn list_of_results() -> Vec<Result<i64, DivisionError>> {
let numbers = [27, 297, 38502, 81];
let division_results = numbers.into_iter().map(|n| divide(n, 27));
division_results.into_iter().collect()
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_success() {
assert_eq!(divide(81, 9), Ok(9));
}
#[test]
fn test_divide_by_0() {
assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero));
}
#[test]
fn test_integer_overflow() {
assert_eq!(divide(i64::MIN, -1), Err(DivisionError::IntegerOverflow));
}
#[test]
fn test_not_divisible() {
assert_eq!(divide(81, 6), Err(DivisionError::NotDivisible));
}
#[test]
fn test_divide_0_by_something() {
assert_eq!(divide(0, 81), Ok(0));
}
#[test]
fn test_result_with_list() {
assert_eq!(result_with_list().unwrap(), [1, 11, 1426, 3]);
}
#[test]
fn test_list_of_results() {
assert_eq!(list_of_results(), [Ok(1), Ok(11), Ok(1426), Ok(3)]);
}
}
if b == 0 {
return Err(DivisionError::DivideByZero);
}
let (r, overflow) = a.overflowing_div(b);
if overflow {
return Err(DivisionError::IntegerOverflow);
}
if a % b != 0 {
return Err(DivisionError::NotDivisible);
}
Ok(r)
fn factorial(num: u64) -> u64 {
// Complete this function to return the factorial of `num` which is
// defined as `1 * 2 * 3 * … * num`.
// https://en.wikipedia.org/wiki/Factorial
//
// Do not use:
// - early returns (using the `return` keyword explicitly)
// Try not to use:
// - imperative style loops (for/while)
// - additional variables
// For an extra challenge, don't use:
// - recursion
// (1..=num).fold(1, |r, x| r * x)
(1..=num).product()
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn factorial_of_0() {
assert_eq!(factorial(0), 1);
}
#[test]
fn factorial_of_1() {
assert_eq!(factorial(1), 1);
}
#[test]
fn factorial_of_2() {
assert_eq!(factorial(2), 2);
}
#[test]
fn factorial_of_4() {
assert_eq!(factorial(4), 24);
}
}
(1..=num).fold(1, |r, x| r * x)
(1..=num).product()
// Let's define a simple model to track Rustlings' exercise progress. Progress
// will be modelled using a hash map. The name of the exercise is the key and
// the progress is the value. Two counting functions were created to count the
// number of exercises with a given progress. Recreate this counting
// functionality using iterators. Try to not use imperative loops (for/while).
use std::collections::HashMap;
#[derive(Clone, Copy, PartialEq, Eq)]
enum Progress {
None,
Some,
Complete,
}
fn count_for(map: &HashMap<String, Progress>, value: Progress) -> usize {
let mut count = 0;
for val in map.values() {
if *val == value {
count += 1;
}
}
count
}
// Implement the functionality of `count_for` but with an iterator instead
// of a `for` loop.
fn count_iterator(map: &HashMap<String, Progress>, value: Progress) -> usize {
// `map` is a hash map with `String` keys and `Progress` values.
// map = { "variables1": Complete, "from_str": None, … }
map.iter()
.map(|(_k, p)| if *p == value { 1 } else { 0 })
.sum()
}
fn count_collection_for(collection: &[HashMap<String, Progress>], value: Progress) -> usize {
let mut count = 0;
for map in collection {
for val in map.values() {
if *val == value {
count += 1;
}
}
}
count
}
// Implement the functionality of `count_collection_for` but with an
// iterator instead of a `for` loop.
fn count_collection_iterator(collection: &[HashMap<String, Progress>], value: Progress) -> usize {
// `collection` is a slice of hash maps.
// collection = [{ "variables1": Complete, "from_str": None, … },
// { "variables2": Complete, … }, … ]
collection.iter().map(|m| count_iterator(m, value)).sum()
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
fn get_map() -> HashMap<String, Progress> {
use Progress::*;
let mut map = HashMap::new();
map.insert(String::from("variables1"), Complete);
map.insert(String::from("functions1"), Complete);
map.insert(String::from("hashmap1"), Complete);
map.insert(String::from("arc1"), Some);
map.insert(String::from("as_ref_mut"), None);
map.insert(String::from("from_str"), None);
map
}
fn get_vec_map() -> Vec<HashMap<String, Progress>> {
use Progress::*;
let map = get_map();
let mut other = HashMap::new();
other.insert(String::from("variables2"), Complete);
other.insert(String::from("functions2"), Complete);
other.insert(String::from("if1"), Complete);
other.insert(String::from("from_into"), None);
other.insert(String::from("try_from_into"), None);
vec![map, other]
}
#[test]
fn count_complete() {
let map = get_map();
assert_eq!(count_iterator(&map, Progress::Complete), 3);
}
#[test]
fn count_some() {
let map = get_map();
assert_eq!(count_iterator(&map, Progress::Some), 1);
}
#[test]
fn count_none() {
let map = get_map();
assert_eq!(count_iterator(&map, Progress::None), 2);
}
#[test]
fn count_complete_equals_for() {
let map = get_map();
let progress_states = [Progress::Complete, Progress::Some, Progress::None];
for progress_state in progress_states {
assert_eq!(
count_for(&map, progress_state),
count_iterator(&map, progress_state),
);
}
}
#[test]
fn count_collection_complete() {
let collection = get_vec_map();
assert_eq!(
count_collection_iterator(&collection, Progress::Complete),
6,
);
}
#[test]
fn count_collection_some() {
let collection = get_vec_map();
assert_eq!(count_collection_iterator(&collection, Progress::Some), 1);
}
#[test]
fn count_collection_none() {
let collection = get_vec_map();
assert_eq!(count_collection_iterator(&collection, Progress::None), 4);
}
#[test]
fn count_collection_equals_for() {
let collection = get_vec_map();
let progress_states = [Progress::Complete, Progress::Some, Progress::None];
for progress_state in progress_states {
assert_eq!(
count_collection_for(&collection, progress_state),
count_collection_iterator(&collection, progress_state),
);
}
}
}
map.iter().map(|(_k, p)| if *p == value { 1 } else { 0 }).sum()