如何编写一个简单地反转迭代的自定义“IntoIterator”实现?
How do I write a custom `IntoIterator` implementation that simply reverses the iteration?
我是 Rust 新手,我正在尝试实现具有 Vec
的自定义 struct
。我希望这个自定义结构是可迭代的,并且以相反的顺序在内部 Vec
上迭代。
到目前为止,我的理解是我需要实现 IntoIterator
特征,并最终实现自定义 Iterator
,IntoIterator
将自定义结构转换为该自定义结构。由于我只想反转 Vec
上的迭代,我正在考虑重新使用标准库已经提供的内容。
这是我的结构:
pub struct BitMap {
content: Vec<u64>,
}
这就是我尝试实现 IntoIterator
:
的方式
impl<'a> iter::IntoIterator for &'a BitMap {
type Item = u64;
type IntoIter = iter::Rev<slice::Iter<'a, Self::Item>>;
fn into_iter(self) -> Self::IntoIter {
(&(self.content)).iter().rev()
}
}
但是编译器抱怨:
47 | type IntoIter = iter::Rev<slice::Iter<'a, Self::Item>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found reference
我正在努力理解如何实现这个简单的事情。
更新
谢谢E_net4 says don't copy that for your !
考虑到您提到您的解决方案需要复制元素,我试图实现一个试图避免它的版本,这就是我想出的:
impl<'a> iter::IntoIterator for &'a BitMap {
type Item = u64;
type IntoIter = BitMapIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
BitMapIterator::new(&self.content)
}
}
pub struct BitMapIterator<'a> {
content: &'a Vec<u64>,
index: usize,
}
impl<'a> BitMapIterator<'a> {
fn new(content: &'a Vec<u64>) -> Self {
BitMapIterator {
content,
index: content.len(),
}
}
}
impl iter::Iterator for BitMapIterator<'_> {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
if self.index == 0 {
None
} else {
self.index -= 1;
Some(self.content[self.index])
}
}
}
但是如您所见,这需要我实现自定义迭代器并使其成为 public。这似乎做我想做的,如果我在没有复制元素的情况下理解正确,但我不知道这个解决方案是多么地道,它基本上不重复使用 std lib 提供的任何东西。
在向量上调用 .iter()
会创建一个项目的非拥有迭代器,它将位于不可变引用之后。并且 &u64
项的迭代器不履行 u64
项的迭代器的角色。
考虑到 u64
的复制成本低,用 .copied
调整迭代器足以获得返回实际值的迭代器。复制的迭代器是惰性的,它只在遍历项目时复制它们。
use std::{iter, slice};
pub struct BitMap {
content: Vec<u64>,
}
impl<'a> iter::IntoIterator for &'a BitMap {
type Item = u64;
type IntoIter = iter::Copied<iter::Rev<slice::Iter<'a, Self::Item>>>;
fn into_iter(self) -> Self::IntoIter {
self.content.iter().rev().copied()
}
}
另请参阅:
- Creating the method copied for IntoIterator
我是 Rust 新手,我正在尝试实现具有 Vec
的自定义 struct
。我希望这个自定义结构是可迭代的,并且以相反的顺序在内部 Vec
上迭代。
到目前为止,我的理解是我需要实现 IntoIterator
特征,并最终实现自定义 Iterator
,IntoIterator
将自定义结构转换为该自定义结构。由于我只想反转 Vec
上的迭代,我正在考虑重新使用标准库已经提供的内容。
这是我的结构:
pub struct BitMap {
content: Vec<u64>,
}
这就是我尝试实现 IntoIterator
:
impl<'a> iter::IntoIterator for &'a BitMap {
type Item = u64;
type IntoIter = iter::Rev<slice::Iter<'a, Self::Item>>;
fn into_iter(self) -> Self::IntoIter {
(&(self.content)).iter().rev()
}
}
但是编译器抱怨:
47 | type IntoIter = iter::Rev<slice::Iter<'a, Self::Item>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found reference
我正在努力理解如何实现这个简单的事情。
更新
谢谢E_net4 says don't copy that for your
考虑到您提到您的解决方案需要复制元素,我试图实现一个试图避免它的版本,这就是我想出的:
impl<'a> iter::IntoIterator for &'a BitMap {
type Item = u64;
type IntoIter = BitMapIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
BitMapIterator::new(&self.content)
}
}
pub struct BitMapIterator<'a> {
content: &'a Vec<u64>,
index: usize,
}
impl<'a> BitMapIterator<'a> {
fn new(content: &'a Vec<u64>) -> Self {
BitMapIterator {
content,
index: content.len(),
}
}
}
impl iter::Iterator for BitMapIterator<'_> {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
if self.index == 0 {
None
} else {
self.index -= 1;
Some(self.content[self.index])
}
}
}
但是如您所见,这需要我实现自定义迭代器并使其成为 public。这似乎做我想做的,如果我在没有复制元素的情况下理解正确,但我不知道这个解决方案是多么地道,它基本上不重复使用 std lib 提供的任何东西。
在向量上调用 .iter()
会创建一个项目的非拥有迭代器,它将位于不可变引用之后。并且 &u64
项的迭代器不履行 u64
项的迭代器的角色。
考虑到 u64
的复制成本低,用 .copied
调整迭代器足以获得返回实际值的迭代器。复制的迭代器是惰性的,它只在遍历项目时复制它们。
use std::{iter, slice};
pub struct BitMap {
content: Vec<u64>,
}
impl<'a> iter::IntoIterator for &'a BitMap {
type Item = u64;
type IntoIter = iter::Copied<iter::Rev<slice::Iter<'a, Self::Item>>>;
fn into_iter(self) -> Self::IntoIter {
self.content.iter().rev().copied()
}
}
另请参阅:
- Creating the method copied for IntoIterator