如何从& Vec< T>中创建& T的迭代器或Vec& T? [英] How can I create an iterator of &T from either a &Vec<T> or Vec<&T>?

查看:77
本文介绍了如何从& Vec< T>中创建& T的迭代器或Vec& T?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有两个变体的枚举.它包含对String s的Vec的引用,或者包含对String s的Vec的引用:

I have an enum with two variants. Either it contains a reference to a Vec of Strings or it contains a Vec of references to Strings:

enum Foo<'a> {
    Owned(&'a Vec<String>),
    Refs(Vec<&'a String>),
}

我想遍历该枚举中对String的引用.

I want to iterate over references to the Strings 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);
    }
}

这篇关于如何从&amp; Vec&lt; T&gt;中创建&amp; T的迭代器或Vec&amp; T?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆