简体   繁体   English

如何实现一个委托给 HashMap::values() 的迭代器

[英]how to implement an iterator that delegates to HashMap::values()

I am trying to implement a datastructure to store 'registers' in groups.我正在尝试实现一个数据结构来分组存储“寄存器”。 There is a master list which I am considering the owner of the register data.有一个主列表,我正在考虑注册数据的所有者。

I have the following :我有以下内容

use std::collections::hash_map::HashMap;

pub struct Register {
    pub name: String,
    pub address: u16,
}

// map with references to 'master' list of registers
type RegisterMap<'a> = HashMap<String, &'a Register>;

struct RegisterGroup<'a> {
    start_address: u16,
    registers: RegisterMap<'a>,
}

struct RegisterGroupIter<'a> {
    inner: std::collections::hash_map::Values<'a,String,&'a Register>,
}

impl<'a> Iterator for RegisterGroupIter<'a> {
    type Item = &'a Register;
    fn next(&mut self) -> Option<&'a Register> {
        self.inner.next()
    }
}
impl<'a> RegisterGroup<'a> {

    // return iterator over references to Register
    fn registers(&self) -> RegisterGroupIter {
        RegisterGroupIter {
            inner: self.registers.values(),
        }
    }
}

Is this reasonable/idiomatic?这是合理/惯用的吗? If so what is the correct setup for the item type wrt references/lifetimes etc?如果是这样,项目类型 wrt 引用/寿命等的正确设置是什么? Otherwise what should I be doing instead?否则我应该怎么做?

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/main.rs:22:9
   |
21 |     fn next(&mut self) -> Option<&'a Register> {
   |                           -------------------- expected `std::option::Option<&'a Register>` because of return type
22 |         self.inner.next()
   |         ^^^^^^^^^^^^^^^^^ expected struct `Register`, found `&Register`
   |
   = note: expected enum `std::option::Option<&'a Register>`
              found enum `std::option::Option<&&'a Register>`

Since the values iterator of a HashMap yields references to the values type, and the values type is a reference itself in this case, the iterator items are of type &&Register .由于HashMap的 values 迭代器产生对 values 类型的引用,并且在这种情况下 values 类型本身就是一个引用,因此迭代器项的类型是&&Register This means you need to dereference the items before returning them in your iterator.这意味着您需要先取消引用这些项目,然后再将它们返回到您的迭代器中。 The easiest way to dereference inside an option is to use the copied() method:在选项中取消引用的最简单方法是使用copied()方法:

impl<'a> Iterator for RegisterGroupIter<'a> {
    type Item = &'a Register;
    fn next(&mut self) -> Option<&'a Register> {
        self.inner.next().copied()
    }
}

I'm not sure why you store the name both as the hash map key and inside the Register struct.我不确定您为什么将名称存储为 hash map 键和Register结构内。 I'd usually try to normalize the data and only sore the name as the map keys.我通常会尝试规范化数据,只将名称命名为 map 键。

You don't really need to implement your own iterator type here.您实际上并不需要在这里实现自己的迭代器类型。 Directly returning the values iterator of the hash map will work just fine:直接返回 hash map 的值迭代器就可以了:

impl RegisterGroup<'_> {
    fn registers(&self) -> impl Iterator<Item = &Register> {
        self.registers.values().copied()
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM