从 HashMap 获取第一个元素

10

我有一个 HashMap,需要获取第一个元素:

type VarIdx = std::collections::HashMap<u16, u8>;

fn get_first_elem(idx: VarIdx) -> u16 {
    let it = idx.iter();
    let ret = match it.next() {
        Some(x) => x,
        None => -1,
    };
    ret
}

fn main() {}

但是代码无法编译:

error[E0308]: match arms have incompatible types
 --> src/main.rs:5:15
  |
5 |       let ret = match it.next() {
  |  _______________^
6 | |         Some(x) => x,
7 | |         None => -1,
8 | |     };
  | |_____^ expected tuple, found integral variable
  |
  = note: expected type `(&u16, &u8)`
             found type `{integer}`
note: match arm with an incompatible type
 --> src/main.rs:7:17
  |
7 |         None => -1,
  |                 ^^

我该如何修复它?


4
强烈建议你阅读任何方法的文档,尤其是在出现错误时。例如,HashMap::iter只有很少的文档,但它可以解释你遇到的所有问题:“一个以随机顺序访问所有键值对的迭代器。迭代器元素类型为(&'a K, &'a V)。” - Shepmaster
2个回答

18

HashMap 中,没有所谓的“第一个”项目。存储值的顺序以及迭代它们的顺序没有任何保证

如果顺序很重要,那么可以考虑切换到BTreeMap,它根据键保留顺序。

如果您只需要获取任何值,也就是遇到的第一个值,则可以类似于原始代码创建一个迭代器,仅获取第一个值:

fn get_first_elem(idx: VarIdx) -> i16 {
    match idx.values().next() {
        Some(&x) => x as i16,
        None => -1,
    }
}

values()方法创建一个仅包含值的迭代器。你出现错误的原因是iter()会创建一个键和值成对的迭代器,这就是为什么你得到了“expected tuple”错误。

为了编译通过,我必须改变一些其他的东西: -1不是一个有效的u16值,所以必须变成i16,并且你的值是u8,所以必须强制转换为i16

另外值得一提的是,返回-1表示失败并不是Rust语言的最佳实践。这就是Option存在的原因,并且鉴于next()已经返回Option,这很容易实现:

fn get_first_elem(idx: VarIdx) -> Option<u8> {
    idx.values().copied().next()
}

.copied()是必需的,以将迭代器的&u8值转换为u8


7

HashMap::iter 返回一个迭代器,遍历(&Key, &Value)键值对。你需要的是 HashMap::values,它返回一个仅包含HashMap 值的迭代器。

请注意,值的顺序是随机的,它与您放置值的顺序或实际值无关。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接