Filter 无法将已筛选的Vec收集到自身中

Filter 无法将已筛选的Vec收集到自身中,filter,rust,prime-factoring,Filter,Rust,Prime Factoring,我已经开始研究Rust中的项目Euler问题,其中最简单的快速方法是实现一个 在这样做的过程中,我的算法创建了一个迭代器,然后从中过滤出非素数并将其分配回原始向量,但我收到了一个错误,Vec无法从iterator构建 代码: fn eratosthenes_筛(限值:u32)->Vec{ 让mut素数为:Vec=Vec::new(); 让mut range:Vec=(2..=limit).collect(); 设mut length=range.len(); 环路{ 设p=范围[0]; 素数推

我已经开始研究Rust中的项目Euler问题,其中最简单的快速方法是实现一个

在这样做的过程中,我的算法创建了一个迭代器,然后从中过滤出非素数并将其分配回原始向量,但我收到了一个错误,
Vec
无法从
iterator
构建


代码:

fn eratosthenes_筛(限值:u32)->Vec{
让mut素数为:Vec=Vec::new();
让mut range:Vec=(2..=limit).collect();
设mut length=range.len();
环路{
设p=范围[0];
素数推(p);
range=range.iter().filter(|&n |*n%p!=0.collect();
如果长度==范围.len(){
打破
}
长度=range.len();
}
素数
}
错误:

error[E0277]:无法通过对`&u32类型的元素使用迭代器构建`std::vec::vec`类型的集合`
-->src\main.rs:42:55
|
42 | range=range.iter().filter(|&n |*n%p!=0.collect();
|^^^^^无法从“std::iter::Iterator”生成“std::vec::vec”类型的集合`
|
=help:trait`std::iter::fromtiterator`未为`std::vec::vec'实现`

为什么闭包将值包装在额外的借项中?

解释 根据错误消息,表达式
range.iter().filter(|&n |*n%p!=0)
&u32
类型项的迭代器:对
u32
的引用。您希望在
u32上按值使用迭代器。让我们倒着走:

迭代器链的
过滤器(…)
部分实际上与您的问题无关。当我们看一眼,我们看到它回来了。此类型实现了迭代器

impl<I: Iterator, P> Iterator for Filter<I, P>
where
    P: FnMut(&I::Item) -> bool,
{
    type Item = I::Item;
    // ...
}
这里我们看到,条目类型是对
T
(向量的元素类型)的引用


解决 在一般情况下,您可以对任何迭代引用的迭代器调用
.cloned()
,以获得一个新的迭代器,该迭代器通过值(通过克隆每个项)迭代项。对于实现
Copy
的类型,您可以(并且应该)使用
.copied()
。例如,
range.iter().filter(|&n |*n%p!=0).copied().collect()

但是,在这种情况下,有一个更好的解决方案:因为以后不再需要向量,所以可以只调用
到iter()
而不是
iter()
,以便通过值直接获得对
u32
的迭代器。这会消耗向量,使其无法访问。但是,如前所述,这不是一个问题

range=range.into_iter().filter(|&n|n%p!=0.collect();
还请注意,我删除了
*n
中的
*
,因为不再需要取消引用

其他提示 总是重新分配一个新的向量不是很快。Eratosthenes筛的经典实现方式不同:不存储数字,只存储布尔值来表示每个数字是否为素数。数字从不显式存储,而是使用向量/数组的索引隐式存储


要使其真正快速,不应使用
Vec
,而应使用专用的位向量
Vec
每个
bool
存储一个字节,尽管只需要一位。提供这种位向量的事实上的板条箱是
位向量
,这也方便地显示了埃拉托什尼筛的示例实现。

这实际上不是埃拉托什尼筛;这是审判庭。不同之处在于,在试除法中,您通过
p
测试所有不能被小于
p
的素数整除的数字的可整除性;在Eratosthenes筛中,你只处理每一个
p
th数,不管它是否已经被更小的素数整除过。我鼓励您阅读,它分析了这两种方法的时间复杂性,并描述了一种简洁的类似迭代器的方法来实现真正的筛子(当然,如果试算法足以解决问题,那么使用较慢的方法也没有什么丢脸的,尤其是如果它更具可读性的话)@trentcl我已经有10年没有上过数学课了,所以我很欣赏这个方向!也许不完全是复制品
impl<I: Iterator, P> Iterator for Filter<I, P>
where
    P: FnMut(&I::Item) -> bool,
{
    type Item = I::Item;
    // ...
}