我想将 HashSet[0] 的元素移动到 HashSet[1],error[E0502]: cannot borrow `hsets` as mutable because it is also borrowed as immutable

I want move elements of HashSet[0] to HashSet[1], error[E0502]: cannot borrow `hsets` as mutable because it is also borrowed as immutable

我想将 HashSet[0] 的元素移动到 HashSet[1]:

项目1:直接remove() insert()

错误,无法编译。

use std::collections::HashSet;

fn main() {
    let mut hsets = vec![];

    // first set
    hsets.push(HashSet::new());
    hsets[0].insert("a1");
    hsets[0].insert("a2");

    // second set
    hsets.push(HashSet::new());
    hsets[1].insert("b1");
    hsets[1].insert("b2");

    // I want move elements of HashSet[0] to HashSet[1]
    for &v in hsets[0].iter() {
        hsets[0].remove(v);
        hsets[1].insert(v);
    }

    dbg!(&hsets);
}
error[E0502]: cannot borrow `hsets` as mutable because it is also borrowed as immutable
  --> src/main.rs:17:9
   |
16 |     for &v in hsets[0].iter() {
   |               ---------------
   |               |
   |               immutable borrow occurs here
   |               immutable borrow later used here
17 |         hsets[0].remove(v);
   |         ^^^^^ mutable borrow occurs here

error[E0502]: cannot borrow `hsets` as mutable because it is also borrowed as immutable
error: aborting due to 2 previous errors

项目 2:使用 tmp vec

正确,但需要额外的内存! 事实上,我的hsets数据大小超过56G内存!所以我希望不要增加额外的内存。

use std::collections::HashSet;

fn main() {
    let mut hsets = vec![];

    // first set
    hsets.push(HashSet::new());
    hsets[0].insert("a1");
    hsets[0].insert("a2");

    // second set
    hsets.push(HashSet::new());
    hsets[1].insert("b1");
    hsets[1].insert("b2");

    let mut arr = vec![];
    for &v in hsets[0].iter() {
        arr.push(v);
    }
    for v in arr {
        hsets[0].remove(v);
        hsets[1].insert(v);
    }

    dbg!(&hsets);
}

项目 3:使用 split_at_mut()

正确,但我的 hsets vec 有数百万个元素。 所以可能不是一个好方法。谢谢pretzelhammer让路!

use std::collections::HashSet;

fn main() {
    let mut hsets = vec![];

    // first set
    hsets.push(HashSet::new());
    hsets[0].insert("a1");
    hsets[0].insert("a2");

    // second set
    hsets.push(HashSet::new());
    hsets[1].insert("b1");
    hsets[1].insert("b2");

    dbg!(&hsets);
    assert_eq!(hsets[0].len(), 2);
    assert_eq!(hsets[1].len(), 2);

    // move elements from first set to second set
    let (first, second) = hsets.split_at_mut(1);
    second[0].extend(first[0].drain());

    dbg!(&hsets);
    assert_eq!(hsets[0].len(), 0);
    assert_eq!(hsets[1].len(), 4);
}

correct, but my hsets vec has millions elements. so may be a not good way. thanks

split* 方法(split_atsplit_firstsplit_last 及其可变变体)只是 return 切片和引用,它们以常量执行时间,他们不复制任何东西,他们当然不分配,所以 vec 的大小并不是真正的问题。

如果您有 10 个元素的 vec 并在中间拆分,它将创建两个引用原始向量且长度分别为 5 和 5 的切片,如果您的向量有 1000 万个元素,则切片的长度将为 5000000和 5000000。没有实际区别。