如何解决将 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
}
}
}
虽然这相当低效,因为我们每次都需要遍历键以找到下一个键。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。