![](/img/trans.png)
[英]Rust - create hashmap which uses part of the data it's storing from an iterator
[英]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.