【发布时间】:2019-10-30 02:52:58
【问题描述】:
我学习 Rust 是为了好玩,在编写一个返回第 n 个素数的函数时,我意识到我的解决方案感觉不优雅和浪费。
当我只想遍历其中未验证的部分时,我会遍历整个可能的质数列表。有没有办法在使用 retain() 函数时做到这一点?
我的主要问题是我相信 retain() 函数是为 Vec 实现的,而不是为切片实现的。我尝试查看 slice 文档以获取更多想法,但找不到任何想法。
这里是代码。
let mut prime_list: Vec<u32> = (2..n).collect();
let mut i: usize = 0;
while i < prime_list.len() {
let prime: u32 = prime_list[i];
prime_list.retain(
|x| x <= &prime || x % &prime != 0);
i += 1;
}
所以问题出在函数调用中
prime_list.retain(
|x| x <= &prime || x % &prime != 0);
每次我进入这个循环时,我都不需要检查列表中的每个元素,因为我知道我已经验证了 'i' 之前的元素。
但是 retain() 函数需要遍历整个容器,所以我在其中添加了一个检查 (x
我想做的是优雅地从位置“i”的元素开始,然后遍历列表删除元素。
我知道我可以使用不太优雅的 while 或 for 循环来做到这一点,但我希望有一种 Rust 方式可以优雅地做到这一点。
感谢您的帮助!
编辑:这是一个可能的解决方案,它使用拆分和 filter() 感觉比我认为的更模糊......如果有更好的方法使用 filter() 方法和迭代器,我真的很感激轻推方向正确。
// inside the while loop
let prime: u32 = prime_list[i];
let (left, right) = prime_list.split_at(i);
prime_list = left.iter()
.chain(
right.iter()
.filter(|x| *x == &prime || *x % &prime != 0))
.map(|&x| x)
.collect();
i += 1;
【问题讨论】:
-
像
filter这样的迭代器会起作用吗?我不太明白你的素数算法。 -
非常感谢您的快速回复!我不确定 filter() 是否会起作用,因为我想在 while 循环之外改变并返回 prime_list 。如果我做了一个 filter() ,我是否不必收集结果并以某种方式将其重新分配给 prime_list 变量?我不确定我是否可以重新分配……但我可以快速尝试一下。
-
好的,我更新了它,但我不确定这个解决方案是否更好。我用新的工作版本更新了帖子。
-
我的意思更接近于
prime_list[i..].iter().filter(|| {...}).collect::<Vec<_>>(); -
这适用于收集我刚刚扫描过的矢量部分,但我想收集不需要扫描的部分以及这个过滤的部分。因此,在编辑中,我想我会在
rust right.iter().filter(....)处做类似于您的建议的事情,但是由于我想要两者,所以我首先要 split_at() 然后将它们 chain() 在一起。出于某种原因,因为它是引用的切片,所以在执行 collect() 之前,我必须将每个元素更改为值而不是引用。