繁体   English   中英

在结构中存储 HashMap 的迭代器

[英]Storing an iterator for a HashMap in a struct

编辑

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

我正在使用 serde 从 YAML 文件中解析 Foo 的值,我想让用户一次从 yaml 中获取其中一个存储值,这就是为什么我想在我的结构中存储一个迭代器


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

struct Bar {
    name: String,
    id: u32
}

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

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

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进一步改进,这将允许您有效地取出 parsed 的第一个元素。 这将使不使用克隆变得容易。 但是这样一来,您将只能通过所有已解析的值 go 一次,我认为这实际上是您在用例中想要的。

但我会让你实现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, 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>,
    current_idx: usize,
}

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

    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
        }
    }
}

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

暂无
暂无

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

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