在 HashMap 中搜索一个条目,如果不存在则创建一个
我目前正在做 2021 年代码练习的出现。因为我现在正在尝试学习 Rust,所以我想,我会尝试一下。我目前处于 12/1 天,目标是找到穿过洞穴的方法系统。我这样建模洞穴:
pub enum Cave {
Big(String, Vec<Cave>),
Small(String, Vec<Cave>, bool),
}
字符串是洞穴的标识符,Vec是所有连接的洞穴,Cave::Small中的bool是因为小洞穴只能被访问一次,所以我必须保留跟踪,如果我已经访问过他们。现在我想读取包含数据的文件,创建并连接洞穴。为此,我创建了一个 HashMap<&str, Cave>,在其中存储所有洞穴,并以标识符作为键。为此,我编写了一个函数,它采用 HashMap 和一个 &str(它是标识符)。该函数会查找 HashMap 来检查它是否已在其中,如果没有,则创建一个新的并将其放入 HashMap 中,如下所示:
pub fn assure_cave(cave_system: &mut HashMap<&str, Cave>, name: &str) {
if cave_system.contains_key(name) {
if name
.chars()
.next()
.expect("No name specified")
.is_uppercase()
{
let cave = Cave::Big(name.to_string(), Vec::new());
cave_system.insert(cave.name(), cave);
} else {
let cave = Cave::Small(name.to_string(), Vec::new(), false);
cave_system.insert(cave.name(), cave);
}
};
}
Cave.name() 只是一个小函数,它返回一个对标识符的引用。现在,我在尝试插入 HashMap 的行中遇到两个错误。第一个是在 Cave.name() 处,它表示“cave
的寿命不够长,借用的值寿命不够长”。如果我理解正确的话,这是因为局部变量 Cave 超出了范围,并且 name 不会引用任何内容,这不好。第二个错误是在洞穴中,它显示“无法移出洞穴
,因为它是借来的”。我认为,这是由于洞穴的名称被借用,所以我无法将洞穴移动到地图中,因为名称将指向任何内容。这是正确的吗?我该如何修复它?我刚刚尝试过并且似乎有效的是将 HashMap<&str, Cave>
更改为 HashMap
并使用 cave_system.insert 插入(cave.name().to_string(), Cave)
,但这看起来非常浪费,因为它不必要地复制了很多字符串。是否可以使用对名称的引用作为键,如果可以,如何使用?如果不是,我的解决方法是否正确,或者是否有更理想的方法?
I'm currently doing the advent of code exercises from 2021. Since I try to learn rust at the moment, I thought, I'll give it a go with it. I'm currently at day 12/1 and the objective is to find a way through a cave system. I modeled caves like so:
pub enum Cave {
Big(String, Vec<Cave>),
Small(String, Vec<Cave>, bool),
}
The String is the identifier of the cave, the Vec are all connected Caves, the bool in Cave::Small is due to the fact, that small caves can only be visited one time, so I have to keep track, if I already visited them. Now I want to read the file, which containes the data, create and connect the caves. For that I made a HashMap<&str, Cave>, in which I store all the caves, with the identifier as the key. For that, I wrote a function, that takes said HashMap and an &str, which is the identifier. The function looks into the HashMap to check, if it is already in it, and if not, create a new one and put it in the HashMap, which looks like this:
pub fn assure_cave(cave_system: &mut HashMap<&str, Cave>, name: &str) {
if cave_system.contains_key(name) {
if name
.chars()
.next()
.expect("No name specified")
.is_uppercase()
{
let cave = Cave::Big(name.to_string(), Vec::new());
cave_system.insert(cave.name(), cave);
} else {
let cave = Cave::Small(name.to_string(), Vec::new(), false);
cave_system.insert(cave.name(), cave);
}
};
}
cave.name() is just a small function, which returns a reference to the identifier. Now I get two errors in the line, where I try to insert into the HashMap. The first one is at cave.name(), it says "cave
does not live long enough borrowed value does not live long enough". If I understand that correctly, this is due to the fact, that the local variable cave goes out of scope and name would reference nothing, which is not good. The second error is at cave and it says "cannot move out of cave
because it is borrowed". I think, this is due to the name of the cave being borrowed, so I can't move cave into the map, since name would then point to nothing. Is this correct? How can I fix it? What I just tried and it seems to work is to change HashMap<&str, Cave>
to HashMap<String, Cave>
and insert with cave_system.insert(cave.name().to_string(), cave)
, but this seems pretty wasteful, since it copies a lot of strings unnecessarily. Is it possible to use a reference to the name as the key, and if so, how? And if not, is my workaround the right thing to do, or is there something more ideomatic?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
查看 canton7 和 Jmb 的链接后,我决定保留原样,并采用创建名称的新字符串副本的解决方案。
After looking at the links from canton7 and Jmb, I decided to just leave it as is with the solution of making new string copies of the name.