// vec1.rs
// Your task is to create a `Vec` which holds the exact same elements
// as in the array `a`.
// Make me compile and pass the test!
// Execute the command `rustlings hint vec1` if you need hints.
fn array_and_vec() -> ([i32; 4], Vec<i32>) {
let a = [10, 20, 30, 40]; // a plain array
let v = // TODO: declare your vector here with the macro for vectors
(a, v)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_array_and_vec_similarity() {
let (a, v) = array_and_vec();
assert_eq!(a, v[..]);
}
}
Vector的相关属性在前面说的差不多了。这里就是考察一下vec!宏构造。
let v = vec![10, 20, 30, 40];// TODO: declare your vector here with the macro for vectors
// vec2.rs
// A Vec of even numbers is given. Your task is to complete the loop
// so that each number in the Vec is multiplied by 2.
//
// Make me pass the test!
//
// Execute the command `rustlings hint vec2` if you need
// hints.
fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
for i in v.iter_mut() {
// TODO: Fill this up so that each element in the Vec `v` is
// multiplied by 2.
}
// At this point, `v` should be equal to [4, 8, 12, 16, 20].
v
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vec_loop() {
let v: Vec<i32> = (1..).filter(|x| x % 2 == 0).take(5).collect();
let ans = vec_loop(v.clone());
assert_eq!(ans, v.iter().map(|x| x * 2).collect::<Vec<i32>>());
}
}
这里考察我们遍历vector的元素。方式一般是通过索引一次一次的访问,但是我们如果想要改变元素的值,可以遍历可变vector的每一个元素的可变引用以便能改变它们。
fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
for i in v.iter_mut() { //可变引用
// TODO: Fill this up so that each element in the Vec `v` is
// multiplied by 2.
*i = *i * 2; //可以遍历可变 vector 的每一个元素的可变引用以便能改变他们
}
// At this point, `v` should be equal to [4, 8, 12, 16, 20].
v
}
// hashmap1.rs
// A basket of fruits in the form of a hash map needs to be defined.
// The key represents the name of the fruit and the value represents
// how many of that particular fruit is in the basket. You have to put
// at least three different types of fruits (e.g apple, banana, mango)
// in the basket and the total count of all the fruits should be at
// least five.
//
// Make me compile and pass the tests!
//
// Execute the command `rustlings hint hashmap1` if you need
// hints.
use std::collections::HashMap;
fn fruit_basket() -> HashMap<String, u32> {
let mut basket = // TODO: declare your hash map here.
// Two bananas are already given for you :)
basket.insert(String::from("banana"), 2);
// TODO: Put more fruits in your basket here.
basket
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn at_least_three_types_of_fruits() {
let basket = fruit_basket();
assert!(basket.len() >= 3);
}
#[test]
fn at_least_five_fruits() {
let basket = fruit_basket();
assert!(basket.values().sum::<u32>() >= 5);
}
}
常用集合还有一个,就是哈希map。HashMap<K, V>类型储存了一个键类型K对应一个值类型V的映射。它通过一个哈希函数(hashing function)来实现映射。哈希map可以用于需要任何类型作为键来寻找数据的情况,而不是像vector那样通过索引
题目考察的是新建一个哈希map,我们可以使用new创建,并用insert添加元素。不过首先要use标准库中集合部分的HashMap。
let mut basket = HashMap::new();// TODO: declare your hash map here.
这样题目就能编译成功了。像vector一样,哈希map也将它们的数据储存在堆上,此外,哈希map是同质的:所有的键必须是相同类型,值也必须都是相同类型。
值得注意的是,哈希map insert的时候会有所有权的交接。像i32这样的实现了Copy trait的类型,其值可以拷贝进哈希map。但对于像String这样拥有所有权的值,其值将被移动而哈希map会成为这些值的所有者。
如果将值的引用插入哈希map,这些值本身将不会被移动进哈希map。但是这些引用指向的值必须至少在哈希map有效时也是有效的。
// hashmap2.rs
// A basket of fruits in the form of a hash map is given. The key
// represents the name of the fruit and the value represents how many
// of that particular fruit is in the basket. You have to put *MORE
// THAN 11* fruits in the basket. Three types of fruits - Apple (4),
// Mango (2) and Lychee (5) are already given in the basket. You are
// not allowed to insert any more of these fruits!
//
// Make me pass the tests!
//
// Execute the command `rustlings hint hashmap2` if you need
// hints.
use std::collections::HashMap;
#[derive(Hash, PartialEq, Eq)]
enum Fruit {
Apple,
Banana,
Mango,
Lychee,
Pineapple,
}
fn fruit_basket(basket: &mut HashMap<Fruit, u32>) {
let fruit_kinds = vec![
Fruit::Apple,
Fruit::Banana,
Fruit::Mango,
Fruit::Lychee,
Fruit::Pineapple,
];
for fruit in fruit_kinds {
// TODO: Put new fruits if not already present. Note that you
// are not allowed to put any type of fruit that's already
// present!
}
}
#[cfg(test)]
mod tests {
use super::*;
fn get_fruit_basket() -> HashMap<Fruit, u32> {
let mut basket = HashMap::<Fruit, u32>::new();
basket.insert(Fruit::Apple, 4);
basket.insert(Fruit::Mango, 2);
basket.insert(Fruit::Lychee, 5);
basket
}
#[test]
fn test_given_fruits_are_not_modified() {
let mut basket = get_fruit_basket();
fruit_basket(&mut basket);
assert_eq!(*basket.get(&Fruit::Apple).unwrap(), 4);
assert_eq!(*basket.get(&Fruit::Mango).unwrap(), 2);
assert_eq!(*basket.get(&Fruit::Lychee).unwrap(), 5);
}
#[test]
fn at_least_five_types_of_fruits() {
let mut basket = get_fruit_basket();
fruit_basket(&mut basket);
let count_fruit_kinds = basket.len();
assert!(count_fruit_kinds >= 5);
}
#[test]
fn greater_than_eleven_fruits() {
let mut basket = get_fruit_basket();
fruit_basket(&mut basket);
let count = basket.values().sum::<u32>();
assert!(count > 11);
}
}
这个是搭配match方法向hashmap里存储。
for fruit in fruit_kinds {
// TODO: Put new fruits if not already present. Note that you
// are not allowed to put any type of fruit that's already
// present!
match fruit { //一个枚举和一个以枚举成员作为模式的 match 表达式
Fruit::Apple => basket.insert(Fruit::Apple, 4),
Fruit::Banana => basket.insert(Fruit::Banana, 4),
Fruit::Mango => basket.insert(Fruit::Mango, 2),
Fruit::Lychee => basket.insert(Fruit::Lychee, 5),
Fruit::Pineapple => basket.insert(Fruit::Pineapple,5),
};
}
哈希map其他的性质后续会提到。