英文:
Rust: Iterator that repeats the first and last element of another Iterator?
问题
以下是您要翻译的内容:
有没有一个Iterator
,无论是在std
中还是在维护的crate中,可以重复另一个Iterator
的第一个和最后一个元素,前提是Item
是Clone
的?
示例:
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<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]));
}
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]);
}
请注意,要重复最后一个元素两次,我们需要事先知道迭代器的大小,因此迭代器类型必须实现ExactSizeIterator
,或者您必须提供其他方法来获取长度。
<details>
<summary>英文:</summary>
There'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<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.](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&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<T: Iterator> {
inner: Fuse<T>,
repeat_first: bool,
repeat_last: bool,
next: Option<T::Item>,
}
impl<T: Iterator> Padded<T>
where
T::Item: Clone,
{
fn new(inner: impl IntoIterator<IntoIter = T>) -> 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<T: Iterator> Iterator for Padded<T>
where
T::Item: Clone,
{
type Item = T::Item;
fn next(&mut self) -> Option<Self::Item> {
self.next.take().tap(|next| {
if take(&mut self.repeat_first) {
self.next = next.clone();
} else {
self.next = self.inner.next().or_else(|| {
next.as_ref().filter(|_| take(&mut self.repeat_last)).cloned()
})
}
})
}
}
fn main() {
Padded::new([1, 2, 3]).for_each(|n| print!("{n}"));
}
英文:
I ended up rolling my own.
use std::{mem::take, iter::Fuse};
use tap::Tap;
struct Padded<T: Iterator> {
inner: Fuse<T>,
repeat_first: bool,
repeat_last: bool,
next: Option<T::Item>,
}
impl<T: Iterator> Padded<T>
where
T::Item: Clone,
{
fn new(inner: impl IntoIterator<IntoIter = T>) -> 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<T: Iterator> Iterator for Padded<T>
where
T::Item: Clone,
{
type Item = T::Item;
fn next(&mut self) -> Option<Self::Item> {
self.next.take().tap(|next| {
if take(&mut self.repeat_first) {
self.next = next.clone();
} else {
self.next = self.inner.next().or_else(|| {
next.as_ref().filter(|_| take(&mut self.repeat_last)).cloned()
})
}
})
}
}
fn main() {
Padded::new([1, 2, 3]).for_each(|n| print!("{n}"));
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论