gpt4 book ai didi

rust - 如何在 Rust 中就地修改向量的元素?

转载 作者:行者123 更新时间:2023-11-29 08:10:49 25 4
gpt4 key购买 nike

我正在尝试将对 Vec(一个切片)的不可变引用传递给一个函数,该函数将用递增的值填充 Vec,然后再次迭代它们用零替换其中一些值。 (Eratosthenes 的筛法)。

我认为向量应该是不可变的(向量的数据类型和大小不会改变)但向量的内容应该是可变的(对整数的引用。)

这已被证明是一项艰巨的任务。我已经阅读了有关可变性和借用的内容,并且我觉得我对此有很好的理解。我也粗略地了解了 C 中的引用、取消引用、指针等是如何工作的,但我认为我正在努力使用 Rust 的语法来实现这一点。

我是不是想错了?在 Rust 中,创建(可能很大的)Vec 的副本、对其进行操作并返回它是否更符合习惯?

到目前为止,这是我的代码(无法编译,有很多错误):

#![feature(iterator_step_by)]

pub fn nth(n: usize) {
let size: usize = (2 as f64 * n as f64 * (n as f64).ln()) as usize;
// Set an upper bound for seiving.
let size_sqrt: usize = (size as f64).sqrt().ceil() as usize;
let nums: Vec<&mut usize> = Vec::with_capacity(size);
sieve(nums, &size, &size_sqrt);
}

fn sieve(nums: [&mut usize], size: &usize, size_sqrt: &usize) {
for i in 0..*size {
nums[i] = i;
}
for num in nums {
if num < 2 {
continue;
} else if num > *size_sqrt {
break;
}
for x in (num.pow(2)..size).step_by(*num) {
nums[x] = 0;
}
}
}

最佳答案

My thinking is that the vector is immutable (the data types and size of the vector will never change) but the contents of the vector should be mutable references to integers. Or should they be the actual values of the integers themselves (and not references)?

引用(&'a T&'a mut T)只能引用另一个值拥有的值。引用不能拥有它们的引用对象。

如果您希望有一个函数对集合中不一定连续的某些整数进行操作,那么构建一个整数引用向量可能是个好主意。但是,根据您的代码示例,情况似乎并非如此;向量拥有整数会更简单、更容易。这意味着向量本身需要是可变的。但是,如果您想确保函数不会尝试更改向量的大小,该函数可以接受一个可变的整数切片 &mut [usize] ,而不是对向量的可变引用 ( &mut Vec<usize> )。

In Rust, is it more idiomatic to create a copy of a potentially huge Vec, operate on that, and return it?

这取决于你是否需要使用原来的Vec之后再次。如果你不这样做,那么改变 Vec 会更有效。到位。如果只需要保留原来的Vec在某些情况下而不是在其他情况下,您总是可以 clone() Vec预先。如果您确实需要原件 Vec每次,那么返回一个新的 Vec 可能更有效率,特别是如果您可以使用 collect 从迭代器填充它,因为这将尝试提前分配正确的大小,并且只分配 Vec 中的每个值。一次。


考虑到所有这些,下面是我将如何编写您的代码。请注意,我必须更改 sieve 中的主循环不直接遍历 nums ,因为这会导致借用冲突——for循环需要借用 nums , 但赋值 nums[x]也会尝试在 nums 上进行可变借用而另一个借用是活跃的。我还更改了 &usize参数到 usize ,因为对小的、可复制的类型(例如原始整数)使用引用没有任何好处(事实上,它可能会稍微慢一些)。

#![feature(iterator_step_by)]

pub fn nth(n: usize) {
let size: usize = (2.0 * n as f64 * (n as f64).ln()) as usize;
// Set an upper bound for seiving.
let size_sqrt: usize = (size as f64).sqrt().ceil() as usize;
let mut nums: Vec<usize> = vec![0; size];
sieve(&mut nums, size, size_sqrt);
}

fn sieve(nums: &mut [usize], size: usize, size_sqrt: usize) {
for i in 0..size {
nums[i] = i;
}

for i in 0..size {
let num = nums[i];
if num < 2 {
continue;
}

if num > size_sqrt {
break;
}

for x in (num.pow(2)..size).step_by(num) {
nums[x] = 0;
}
}
}

关于rust - 如何在 Rust 中就地修改向量的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49037703/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com