首页 文章

在循环中引用集合项时,装箱或显式生命周期是正确的解决方案吗?

提问于
浏览
1

在Rust(版本1.x)中,我想在循环中使用集合的元素,例如下面的示例(它会记录它看到的字符并在发现重复的字符时执行某些操作),其中集合在函数内部定义并且仅由循环使用 .

fn do_something(word:&str) -> u32 {
            let mut seen_chars = HashMap::new();
            let mut answer : u32 = 0;
            for (i,c) in word.chars().enumerate() {
            let char_str = Box::new(c.to_string());
            match seen_chars.get(&char_str) {
                    Some(&index) => {
                    answer = answer + index;
                    },
                    None => {seen_chars.insert(char_str,i);}
            }; 

    }
    answer
    }

为了在我的hashmap中存储对c的引用(我在循环之外声明了),我需要将c封装并在堆上分配 . 这感觉无穷无尽,我必须做错事 . 我想知道使用显式生命周期是否是更好的做事方式,下面是我最好的尝试,但我无法编译 .

fn do_something<'a>(word:&str) -> u32 {
            let mut seen_chars = : &'a HashMap<&str,usize> = &HashMap::new();
            let mut answer : u32 = 0;
            for (i,c) in word.chars().enumerate() {
            let char_str =  &'a str = &c.to_string();
            match seen_chars.get(&char_str) {
                    Some(&index) => {
                    answer = answer + index;
                    },
                    None => {seen_chars.insert(char_str,i);}
            }; 

    }
    answer
    }

当我尝试编译时,我得到“错误:借来的值不够长”,并指出“&HashMap :: new()”是问题所在 . 我可以使用生命周期规范来解决这个问题,或者我在这里做错了吗?

1 回答

  • 2

    我不认为你的任何一种方法都是最好的解决方案 . 您可以使用char本身作为HashMap的键,无需将其转换为String:

    fn do_something(word:&str) -> usize {
        let mut seen_chars = HashMap::new();
        let mut answer : usize = 0;
        for (i,c) in word.chars().enumerate() {
            match seen_chars.get(&c) {
                Some(&index) => {
                    answer = answer + index;
                },
                None => {seen_chars.insert(c,i);}
            };
        }
        answer
    }
    

    (我还必须更改 answer 的类型以使其编译,因为 enumerate 给你 usize s . 或者,你可以在必要时将 i 转换为 u32

    如果由于某种原因,您想要使用字符串键而不是 char ,则必须使用自有字符串(即 String )而不是字符串切片( &str ) . 你会得到这样的东西:

    fn do_something(word:&str) -> usize {
        let mut seen_chars : HashMap<String,usize> = HashMap::new();
        let mut answer : usize = 0;
        for (i,c) in word.chars().enumerate() {
            let char_str = c.to_string();
            match seen_chars.get(&char_str) {
                Some(&index) => {
                    answer = answer + index;
                },
                None => {seen_chars.insert(char_str,i);}
            };
        }
        answer
    }
    

    但我强烈怀疑第一个选项是你真正想要的 .

相关问题