将 HashMap 的迭代器存储在结构中 编辑

问题描述

编辑

从建议的解决方案看来,我试图实现的目标似乎是不可能的/不是正确的方法,因此 - 我将在这里解释最终目标:

我正在使用 serde 从 YAML 文件中解析 Foo 的值,并且我想让用户一次从 yaml 中获取这些存储的值之一,这就是我想在我的结构中存储迭代器的原因


我有两个类似于以下的结构:

struct Bar {
    name: String,id: u32
}

struct Foo {
    my_map: HashMap<String,Bar>
}

在我的 Foo 结构中,我希望将迭代器存储到我的 HashMap,以便用户可以根据需要从我的地图中借用值。 理论上,完整的 Foo 类看起来像:

struct Foo {
    my_map: HashMap<String,Bar>,my_map_iter: HashMap<String,Bar>::iterator
}

impl Foo {
    fn get_pair(&self) -> Option<(String,Bar)> {
        // impl...
    }
}

但无论我尝试什么,我似乎都无法实现它并创建这样一个变量(各种编译错误,似乎我只是在尝试做错)。

如果有人能指出实现这一目标的正确方法,并且有更好的方法来实现我正在尝试做的事情,我会很高兴 - 我想知道这一点。

谢谢!

解决方法

我正在使用 serde 从 YAML 文件中解析 Foo 的值

解析它们时,您应该将值放在 Vec 而不是 HashMap 中。

我想您拥有的值也有名称,这就是您认为 HashMap 会很好的原因。你可以这样存储它们:

let parsed = vec![]

for _ in 0..n_to_parse {
    // first item of the tuple is the name second is the value
    let key_value = ("Get from","serde");
    parsed.push(key_value);
}

然后,一旦您像这样存储它,就可以通过跟踪当前索引轻松从中获取对:

struct ParsedHolder {
    parsed: Vec<(String,String)>,current_idx: usize,}

impl ParsedHolder {
    fn new(parsed: Vec<(String,String)>) -> Self {
        ParsedHolder {
            parsed,current_idx: 0,}
    }

    fn get_pair(&mut self) -> Option<&(String,String)> {
        if let Some(pair) = self.parsed.get(self.current_idx) {
            self.current_idx += 1;
            Some(pair)

        } else {
            self.current_idx = 0;
            None
        }
    }
}

现在可以通过使用 VecDeque 进一步改进,这将允许您有效地取出已解析的第一个元素。这将使不使用克隆变得容易。但是这样你就只能遍历一次所有解析的值,我认为这实际上是你在用例中想要的。

但我会让你实现VecDeque ?

,

之所以如此困难,是因为除非我们在迭代时确保 HashMap 没有发生变异,否则我们可能会遇到一些麻烦。确保 HashMap 在迭代器存活之前是不可变的:

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

struct Foo<'a> {
    my_map: &'a HashMap<u8,u8>,iterator: Iter<'a,u8,}

fn main() {
    let my_map = HashMap::new();
    let iterator = my_map.iter();

    let f = Foo {
        my_map: &my_map,iterator: iterator,};
}

如果您可以确定或知道 HashMap 不会有新键或从中删除键(使用现有键编辑值很好),那么您可以这样做:

struct Foo {
    my_map: HashMap<String,String>,}

impl Foo {
    fn new(my_map: HashMap<String,String>) -> Self {
        Foo {
            my_map,}
    }

    fn get_pair(&mut self) -> Option<(&String,&String)> {
        if let Some(pair) = self.my_map.iter().skip(self.current_idx).next() {
            self.current_idx += 1;
            Some(pair)

        } else {
            self.current_idx = 0;
            None
        }
    }

    fn get_pair_cloned(&mut self) -> Option<(String,String)> {
        if let Some(pair) = self.my_map.iter().skip(self.current_idx).next() {
            self.current_idx += 1;
            Some((pair.0.clone(),pair.1.clone()))

        } else {
            self.current_idx = 0;
            None
        }
    }
}

虽然这相当低效,因为我们每次都需要遍历键以找到下一个键。