乌龙茶馆

vec1

// 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

// 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

// 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

// 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其他的性质后续会提到。