带有hashmap和vec索引的Rust自引用结构

e1xvtsh3  于 2023-04-06  发布在  其他
关注(0)|答案(1)|浏览(165)

我需要建立一个索引,首先检查store向量中是否已经存在一个字符串,如果不存在,将其添加到store中并获取其位置。
一旦完成,我将需要消耗存储,并丢弃索引。我想避免创建每个字符串两次(一次为索引,一次为存储)。

struct StringIndex {
    store: Vec<String>,
    index: HashMap<&'this str, usize>,
}

impl StringIndex {
  pub fn get_or_insert(&mut self, key: &str) -> usize {
    match self.index.entry(key) {
      Occupied(v) => v.key(),
      Vacant(v) => {
        let idx = self.store.len();
        self.store.push(key.to_string());  // Create a new clone
        v.insert(idx);
        idx
      }
    }
  }
}

我看了self_cell和ouroboros,但似乎都没有针对这个用例……或者没有?

ldxq2e6h

ldxq2e6h1#

添加一个项目,如果它不是一个vec可以做如下。
Playground

fn main() {
    let mut store: Vec<String> = Vec::new();
    
    store.push("Item 1".to_string());
    store.push("Item 2".to_string());
    store.push("Item 3".to_string());
    store.push("Item 4".to_string());
    
    assert_eq!(get_index_or_add("Item 3", &mut store), 2);
    assert_eq!(get_index_or_add("Item 5", &mut store), 4);
}

fn get_index_or_add(s: &str, v: &mut Vec<String>) -> usize {
    match v.iter().position(|x| x == s) {
        Some(i) => i,
        None => {
            v.push(s.to_string());
            v.len() - 1
        }
    }
}

演练

v.iter().这将我们的向量变成一个迭代器。
v.iter().position(f)我们调用position方法,该方法将搜索直到找到匹配或到达终点。
由于有两种可能性Some(index) = We found a match. Or None我们没有找到匹配。所以我们匹配选项。在第一种情况下,我们只返回索引。在第二种情况下,我们首先将字符串推到向量v.push(s)上,然后返回向量的长度减去1 v.len() - 1

相关问题