【发布时间】:2017-02-17 10:57:23
【问题描述】:
我来自 Java/C#/JavaScript 背景,我正在尝试实现一个 Dictionary,它将为每个传递的字符串分配一个永不改变的 id。字典应该能够通过指定的 id 返回一个字符串。这允许在文件系统中更有效地存储一些具有大量重复字符串的数据,因为只会存储字符串的 id 而不是整个字符串。
我认为带有 HashMap 和 Vec 的结构可以,但结果比这更复杂。
我开始使用&str 作为HashMap 的键和Vec 的项目,如下例所示。 HashMap 的值用作Vec 的索引。
pub struct Dictionary<'a> {
values_map: HashMap<&'a str, u32>,
keys_map: Vec<&'a str>
}
impl<'a> Dictionary<'a> {
pub fn put_and_get_key(&mut self, value: &'a str) -> u32 {
match self.values_map.get_mut(value) {
None => {
let id_usize = self.keys_map.len();
let id = id_usize as u32;
self.keys_map.push(value);
self.values_map.insert(value, id);
id
},
Some(&mut id) => id
}
}
}
这工作得很好,直到发现strs 需要存储在某个地方,最好也存储在同一个struct 中。我尝试将Box<str> 存储在Vec 和&'a str 中HashMap。
pub struct Dictionary<'a> {
values_map: HashMap<&'a str, u32>,
keys_map: Vec<Box<str>>
}
借用检查器当然不允许这样做,因为当从 Vec 中删除项目时(或者实际上有时将另一个项目添加到 Vec但这是一个题外话)。
我知道我需要编写unsafe 代码或使用某种形式的共享所有权,其中最简单的一种似乎是Rc。 Rc<Box<str>> 的用法看起来像是引入了双重间接,但目前似乎没有简单的方法来构造 Rc<str>。
pub struct Dictionary {
values_map: HashMap<Rc<Box<str>>, u32>,
keys_map: Vec<Rc<Box<str>>>
}
impl Dictionary {
pub fn put_and_get_key(&mut self, value: &str) -> u32 {
match self.values_map.get_mut(value) {
None => {
let id_usize = self.keys_map.len();
let id = id_usize as u32;
let value_to_store = Rc::new(value.to_owned().into_boxed_str());
self.keys_map.push(value_to_store);
self.values_map.insert(value_to_store, id);
id
},
Some(&mut id) => id
}
}
}
就所有权语义而言,一切似乎都很好,但上面的代码无法编译,因为HashMap 现在需要Rc,而不是&str:
error[E0277]: the trait bound `std::rc::Rc<Box<str>>: std::borrow::Borrow<str>` is not satisfied
--> src/file_structure/sample_dictionary.rs:14:31
|
14 | match self.values_map.get_mut(value) {
| ^^^^^^^ the trait `std::borrow::Borrow<str>` is not implemented for `std::rc::Rc<Box<str>>`
|
= help: the following implementations were found:
= help: <std::rc::Rc<T> as std::borrow::Borrow<T>>
问题:
- 有没有办法构造一个
Rc<str>? - 还有哪些其他结构、方法或途径可以帮助解决此问题。本质上,我需要一种方法来有效地存储两个映射
string-by-id和id-by-string并能够通过&str检索 id,即没有任何过多的分配。
【问题讨论】:
-
Rc<str>上的相关问题:stackoverflow.com/questions/31685697/… -
我可以相信unsized coercions 至少可以在夜间实现,但我无法立即看到这样做的方法。
-
@ChrisEmerson:就像
owning_ref,在这种情况下它可以很好地工作。