如何从& Vec< T>中创建& T的迭代器或Vec& T? [英] How can I create an iterator of &T from either a &Vec<T> or Vec<&T>?
问题描述
我有一个带有两个变体的枚举.它包含对String
s的Vec
的引用,或者包含对String
s的Vec
的引用:
I have an enum with two variants. Either it contains a reference to a Vec
of String
s or it contains a Vec
of references to String
s:
enum Foo<'a> {
Owned(&'a Vec<String>),
Refs(Vec<&'a String>),
}
我想遍历该枚举中对String
的引用.
I want to iterate over references to the String
s in this enum.
我尝试在Foo
上实现一个方法,但不知道如何使其返回正确的迭代器:
I tried to implement a method on Foo
, but don't know how to make it return the right iterator:
impl<'a> Foo<'a> {
fn get_items(&self) -> Iter<'a, String> {
match self {
Foo::Owned(v) => v.into_iter(),
Foo::Refs(v) => /* what to put here? */,
}
}
}
fn main() {
let test: Vec<String> = vec!["a".to_owned(), "b".to_owned()];
let foo = Foo::Owned(&test);
for item in foo.get_items() {
// item should be of type &String here
println!("{:?}", item);
}
}
在&Vec<T>
和Vec<&T>
上实现这种抽象的惯用方法是什么?只要它实现了IntoIterator
特征,get_items
也可能返回不同的内容,以便我可以在for
循环中使用它.
What is an idiomatic method to achieve this abstraction over &Vec<T>
and Vec<&T>
? get_items
may also return something different, as long as it implements the IntoIterator
trait so that I can use it in the for
loop.
推荐答案
您不能仅为此使用std::slice::Iter
类型.
You can't just use the std::slice::Iter
type for this.
如果您不想复制字符串或向量,则必须实现自己的迭代器,例如:
If you don't want to copy the strings or vector, you'll have to implement your own iterator, for example:
struct FooIter<'a, 'b> {
idx: usize,
foo: &'b Foo<'a>,
}
impl<'a, 'b> Iterator for FooIter<'a, 'b> {
type Item = &'a String;
fn next(&mut self) -> Option<Self::Item> {
self.idx += 1;
match self.foo {
Foo::Owned(v) => v.get(self.idx - 1),
Foo::Refs(v) => v.get(self.idx - 1).map(|s| *s),
}
}
}
impl<'a, 'b> Foo<'a> {
fn get_items(&'b self) -> FooIter<'a, 'b> {
FooIter { idx: 0, foo: self }
}
}
fn main() {
let test: Vec<String> = vec!["a".to_owned(), "b".to_owned()];
let foo = Foo::Owned(&test);
for item in foo.get_items() {
println!("{:?}", item);
}
let a = "a".to_string();
let b = "b".to_string();
let test: Vec<&String> = vec![&a, &b];
let foo = Foo::Refs(test);
for item in foo.get_items() {
println!("{:?}", item);
}
}
这篇关于如何从& Vec< T>中创建& T的迭代器或Vec& T?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!