繁体   English   中英

如何在Rust中修改矢量的元素?

[英]How can I modify elements of a vector in place in Rust?

我试图将对Vec (切片)的不可变引用传递给一个函数,该函数将用递增的值填充Vec ,然后对其进行迭代,再次将其替换为零。

我的想法是向量是不可变的(向量的数据类型和大小永远不会改变),但是向量的内容应该是对整数的可变引用。 还是它们应该是整数本身(而不是引用)的实际值?

事实证明,这是一项艰巨的任务。.我已经阅读了有关可变性和借用的知识,并且我对此感到很了解。 我对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;
        }
    }
}

我的想法是向量是不可变的(向量的数据类型和大小永远不会改变),但是向量的内容应该是对整数的可变引用。 还是它们应该是整数本身(而不是引用)的实际值?

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

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

在Rust中,创建潜在的巨大Vec的副本,对其进行操作并返回它是否更加惯用?

这取决于之后是否需要再次使用原始Vec 如果您不这样做,那么就地对Vec进行突变会更有效。 如果在某些情况下只需要保留原始Vec ,而在其他情况下则不需要,则可以始终预先clone() Vec 如果确实每次都需要原始Vec ,则返回新Vec可能会更有效,特别是如果您可以使用collect从迭代器填充它,因为这将尝试提前分配正确的大小并仅分配每个Vec 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;
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM