Rust:重复另一个迭代器的第一个和最后一个元素的迭代器?

huangapple go评论62阅读模式
英文:

Rust: Iterator that repeats the first and last element of another Iterator?

问题

以下是您要翻译的内容:

有没有一个Iterator,无论是在std中还是在维护的crate中,可以重复另一个Iterator的第一个和最后一个元素,前提是ItemClone的?

示例:

let iter = [1, 2, 3].into_iter();

assert!(iter.repeat_first_and_last().eq([1, 1, 2, 3, 3]));
英文:

Is there an Iterator, either in std or a maintained crate, that repeats the first and last element of another Iterator given Item is Clone?

Example:

let iter = [1, 2, 3].into_iter();

assert!(iter.repeat_first_and_last().eq([1, 1, 2, 3, 3]));

答案1

得分: 1

以下是您要翻译的代码部分:

use std::iter::Fuse;

pub struct FirstLastRepeat<I, T> {
    iter: Fuse<I>,
    head: Option<T>,
    tail: Option<T>,
    stash: Option<T>,
}

impl<I, T> FirstLastRepeat<I, T>
where
    I: Iterator<Item = T>,
{
    pub fn new(iter: I) -> Self {
        let mut iter = iter.fuse();
        let head = iter.next();
        Self {
            iter,
            head,
            tail: None,
            stash: None,
        }
    }
}

impl<I, T> Iterator for FirstLastRepeat<I, T>
where
    I: Iterator<Item = T>,
    T: Clone,
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        if let v @ Some(_) = self.head.take() {
            self.stash = v.clone();
            return v;
        }
        if let v @ Some(_) = self.tail.take() {
            return v;
        }
        let next = self.stash.take();
        match self.iter.next() {
            v @ Some(_) => self.stash = v,
            None => self.tail = next.clone(),
        }
        next
    }
}

#[test]
fn basic() {
    let iter = [1, 2, 3].into_iter();
    let flr = FirstLastRepeat::new(iter);

    assert!(flr.eq([1, 1, 2, 3, 3]));
}

请注意,我只提供了代码的翻译部分,没有包括任何其他内容。

英文:

You can also roll your own if you want:

use std::iter::Fuse;

pub struct FirstLastRepeat&lt;I, T&gt; {
    iter: Fuse&lt;I&gt;,
    head: Option&lt;T&gt;,
    tail: Option&lt;T&gt;,
    stash: Option&lt;T&gt;,
}

impl&lt;I, T&gt; FirstLastRepeat&lt;I, T&gt;
where
    I: Iterator&lt;Item = T&gt;,
{
    pub fn new(iter: I) -&gt; Self {
        let mut iter = iter.fuse();
        let head = iter.next();
        Self {
            iter,
            head,
            tail: None,
            stash: None,
        }
    }
}

impl&lt;I, T&gt; Iterator for FirstLastRepeat&lt;I, T&gt;
where
    I: Iterator&lt;Item = T&gt;,
    T: Clone,
{
    type Item = T;

    fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
        if let v @ Some(_) = self.head.take() {
            self.stash = v.clone();
            return v;
        }
        if let v @ Some(_) = self.tail.take() {
            return v;
        }
        let next = self.stash.take();
        match self.iter.next() {
            v @ Some(_) =&gt; self.stash = v,
            None =&gt; self.tail = next.clone(),
        }
        next
    }
}

#[test]
fn basic() {
    let iter = [1, 2, 3].into_iter();
    let flr = FirstLastRepeat::new(iter);

    assert!(flr.eq([1, 1, 2, 3, 3]));
}

The only weird edge case here is an original iterator with only one element. It's not clear what the right behaviour here is, but FristLastRepeat will yield it three times which doesn't seem correct in any case. That could be fixed though.

答案2

得分: 0

以下是翻译好的部分:

在`std`或`itertools`中,我不知道有这样的方法。但你可以组合多个迭代器方法来实现这个目标:

```rust
use std::iter::repeat;

fn main() {
    let iter = [1, 2, 3, 4].into_iter();
    let len = iter.len();

    let res: Vec<u8> = iter
        .enumerate()
        .map(|(i, x)| repeat(x).take((i == 0 || i == len - 1).then(|| 2).unwrap_or(1)))
        .flatten()
        .collect();

    assert_eq!(res, vec![1, 1, 2, 3, 4, 4]);
}

Playground

请注意,要重复最后一个元素两次,我们需要事先知道迭代器的大小,因此迭代器类型必须实现ExactSizeIterator,或者您必须提供其他方法来获取长度。


<details>
<summary>英文:</summary>

There&#39;s no method I know of in either `std` or `itertools` for that. You can combine multiple iterator methods to accomplish this, though:

use std::iter::repeat;

fn main() {
let iter = [1, 2, 3, 4].into_iter();
let len = iter.len();

let res: Vec&lt;u8&gt; = iter
    .enumerate()
    .map(|(i, x)| repeat(x).take((i == 0 || i == len - 1).then(|| 2).unwrap_or(1)))
    .flatten()
    .collect();

assert_eq!(res, vec![1, 1, 2, 3, 4, 4]);

}


[Playground.](https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2021&amp;gist=af42f8acfd05b7158867eaa5c3c3561c)

Note that repeating the last element twice requires us to know the size of the iterator beforehand, so the iterator type must implement [`ExactSizeIterator`](https://doc.rust-lang.org/std/iter/trait.ExactSizeIterator.html), or you have to provide some other means to get the length.

</details>



# 答案3
**得分**: 0

我最终还是自己搞定了。

```rust
    use std::{mem::take, iter::Fuse};
    
    use tap::Tap;
    
    struct Padded&lt;T: Iterator&gt; {
        inner: Fuse&lt;T&gt;,
        repeat_first: bool,
        repeat_last: bool,
        next: Option&lt;T::Item&gt;,
    }
    
    impl&lt;T: Iterator&gt; Padded&lt;T&gt;
    where
        T::Item: Clone,
    {
        fn new(inner: impl IntoIterator&lt;IntoIter = T&gt;) -&gt; Self
        where
            T::Item: Clone,
        {
            let mut inner = inner.into_iter().fuse();
            let next = inner.next();
            
            Self { inner, next, repeat_first: true, repeat_last: true, }
        }
    }
    
    impl&lt;T: Iterator&gt; Iterator for Padded&lt;T&gt;
    where
        T::Item: Clone,
    {
        type Item = T::Item;
    
        fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
            self.next.take().tap(|next| {
                if take(&amp;mut self.repeat_first) {
                    self.next = next.clone();
                } else {
                    self.next = self.inner.next().or_else(|| {
                        next.as_ref().filter(|_| take(&amp;mut self.repeat_last)).cloned()
                    })
                }
            })
        }
    }
    
    fn main() {
        Padded::new([1, 2, 3]).for_each(|n| print!(&quot;{n}&quot;));
    }
英文:

I ended up rolling my own.

use std::{mem::take, iter::Fuse};

use tap::Tap;

struct Padded&lt;T: Iterator&gt; {
    inner: Fuse&lt;T&gt;,
    repeat_first: bool,
    repeat_last: bool,
    next: Option&lt;T::Item&gt;,
}

impl&lt;T: Iterator&gt; Padded&lt;T&gt;
where
    T::Item: Clone,
{
    fn new(inner: impl IntoIterator&lt;IntoIter = T&gt;) -&gt; Self
    where
        T::Item: Clone,
    {
        let mut inner = inner.into_iter().fuse();
        let next = inner.next();
        
        Self { inner, next, repeat_first: true, repeat_last: true, }
    }
}

impl&lt;T: Iterator&gt; Iterator for Padded&lt;T&gt;
where
    T::Item: Clone,
{
    type Item = T::Item;

    fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
        self.next.take().tap(|next| {
            if take(&amp;mut self.repeat_first) {
                self.next = next.clone();
            } else {
                self.next = self.inner.next().or_else(|| {
                    next.as_ref().filter(|_| take(&amp;mut self.repeat_last)).cloned()
                })
            }
        })
    }
}

fn main() {
    Padded::new([1, 2, 3]).for_each(|n| print!(&quot;{n}&quot;));
}

huangapple
  • 本文由 发表于 2023年5月10日 20:47:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76218621.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定