【问题标题】:Allocating/instantiating vector of strings/vectors in Rust hashmap?在 Rust 哈希图中分配/实例化字符串/向量的向量?
【发布时间】:2014-02-10 20:55:59
【问题描述】:

我正在尝试从头开始在 Rust 中实现一个玩具哈希图,并在实际初始化我需要的存储桶时遇到困难。我已经使用一组带有其他原语(如 u8)的存储桶(如下面的 sn-p 中的 cmets 所示)来实现这一点。

我不知道如何告诉编译器为我分配一个包含其他向量的可变向量——在本例中为~str。此代码可以编译,但在运行时失败并出现 index out of bounds 错误。

static DEFAULT_NUMBER_OF_BUCKETS: uint = 64;
static DEFAULT_VALUE_LENGTH: uint = 32; //unused

struct NaiveHashMap {
    hashmap_size: uint, //unused.
    string_capacity: uint, //unused.
    //contents: ~[ u8 ]
    contents: ~[ ~str ]
}

impl NaiveHashMap {

    fn new(hash_size: uint, string_size: uint) -> NaiveHashMap {
        NaiveHashMap {
            hashmap_size: hash_size, //unused
            string_capacity: string_size, //unused
            //contents: ~[ 0, ..DEFAULT_NUMBER_OF_BUCKETS ]
            contents: std::vec::with_capacity::<~str>(DEFAULT_NUMBER_OF_BUCKETS)
        }
    }

    fn get_hash(&self, key: &str) -> u32 {
        let hash: u32 = jenkins_hash(key);
        hash % self.hashmap_size.to_u32().unwrap()
    }

    //fn add(&mut self, key: &str, value: u8) {
    fn add(&mut self, key: &str, value: ~str) {
        let bucket = self.get_hash(key);
        self.contents[bucket] = value;
    }

    //fn get(self, key: &str) -> u8 {
    fn get(&self, key: &str) -> ~str {
        let bucket = self.get_hash(key);
        self.contents[bucket].clone()
    }

}

没有调用不安全的 from_buf 分配或只是复制粘贴 std Hashmap 库,我不确定如何继续。

我意识到最好在课堂上传递一个&lt;T&gt;,这样会更灵活,但更愿意先弄清楚这一点。

编辑:修改 get() 以避免捕获整个结构。

【问题讨论】:

    标签: string vector rust


    【解决方案1】:

    据我了解,您想构造一个给定长度的向量,以按索引向其中写入内容。

    你不能在 Rust 中安全地执行此操作,除非你为向量的每个元素指定默认值。它适用于 ~[u8],因为您确实指定了默认值(零),并且因为 u8 是隐式可复制的:

    [0, ..DEFAULT_NUMBER_OF_BUCKETS]
    

    但是您希望~str 的默认值是多少?它是一个指针,在 Rust 中指针不能等于 null,这本来是指针最自然的默认值。我认为~str 的下一个最自然的值是~"",即一个空字符串。您可以使用它来创建N 字符串的向量:

    vec::from_elem(N, ~"")
    

    这将创建一个空的盒装字符串向量。但这也意味着 N 个分配,这不是你应该不考虑就做的事情。

    但是,您不能对任意类型 T 执行此操作,因为通常任意类型 T 没有任何默认值。此外,任意T也可能不是Cloneable,这是from_elem()所要求的。但是你可以从T 创建另一个类型,它有一个默认值。您为此使用Option

    contents: ~[Option<T>]
    

    要克服不可克隆性,您可以使用带有闭包的from_fn() 函数:

    contents: vec::from_fn(N, |_| None)
    

    顺便说一句,它因“索引越界”错误而失败的原因是因为您使用的是with_capacity() 函数。此函数创建一个 length 为零但具有指定 容量 的向量。您可以在向量上使用push() 方法将元素附加到它的末尾,并且在达到其容量之前不会重新分配,但您不能访问添加的元素“外部”的元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多