实现成对迭代器

时间:2017-10-02 22:39:31

标签: iterator rust

我在为一个函数编写代码时遇到问题,该函数接受一个迭代器并返回迭代成对的(Option<T>, T)迭代器

a = [1,2,3]
assert pairwise(a) == `[(None, 1), (Some(1), 2), (Some(2), 3)]
fn pairwise<I, T>(&xs: &I) -> I
where
    I: Iterator<Item = T>,
{
    [None].iter().chain(xs.iter().map(Some)).zip(xs.iter())
}

fn main() {
    let data: Vec<i32> = vec![1, 2, 3];
    let newdata: Vec<Option<i32>, i32> = pairwise(&data).collect();
    println!("{:?}", newdata);
}
error[E0599]: no method named `iter` found for type `I` in the current scope
 --> src/main.rs:3:28
  |
3 |     [None].iter().chain(xs.iter().map(Some)).zip(xs.iter())
  |                            ^^^^
  |

不确定为什么xs不可迭代。我已经在where条款中陈述过它了吗?

1 个答案:

答案 0 :(得分:2)

fn pairwise<I, T>(&xs: &I) -> I

这没有意义。请参阅What is the correct way to return an Iterator?What is the difference between `e1` and `&e2` when used as the for-loop variable?

I: Iterator<Item = T>,

没有理由指明ItemT

[None].iter()

最好使用iter::once

xs.iter()

标准库中没有定义iter方法的特征。也许你的意思是IntoIterator

let data: Vec<i32> = vec![1, 2, 3]

没有理由在此指定类型; i32是默认的整数类型。

Vec<Option<i32>, i32>
Vec<Option<i32>, i32>> // original version

这不是Vec的有效类型,您的原始表单甚至没有平衡符号。

毕竟,你面临艰难的选择。您的示例代码传入一个迭代器,该迭代器具有引用到切片但您已经编写了断言,以便您希望返回非引用。您还试图两次使用任意迭代器;我不能保证这样的事情是可行的。

我看到的最通用的形式是:

use std::iter;

fn pairwise<'a, I>(xs: I) -> Box<Iterator<Item = (Option<I::Item>, I::Item)> + 'a>
where
    I: 'a + IntoIterator + Clone,
{
    let left = iter::once(None).chain(xs.clone().into_iter().map(Some));
    let right = xs.into_iter();
    Box::new(left.zip(right))
}

fn main() {
    let data = vec![1, 2, 3];

    let newdata: Vec<_> = pairwise(&data).collect();
    assert_eq!(newdata, [(None, &1), (Some(&1), &2), (Some(&2), &3)]);

    let newdata: Vec<_> = pairwise(data.iter().cloned()).collect();
    assert_eq!(newdata, [(None, 1), (Some(1), 2), (Some(2), 3)]);
}

另见: