簡體   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