创建包含对另一个集合中项目的引用的集合

Create collection containing references to items in another collection

我有一个按列组织的 table,我想创建一个行向量,这些行是哈希映射,其值是对列中等效值的 mutable 引用,因此然后我可以遍历行,更改将更新原始列中的值的值。我认为这可能是创建一个行的迭代器,而不是一个行的向量,但我更愿意先学习如何做一个向量(如果可能的话),因为这个项目是为了我学习生锈。以下是我到目前为止所拥有的,但我收到了错误

cannot borrow `columns` as mutable more than once at a time
`columns` was mutably borrowed here in the previous iteration of the loop

我找不到解决办法。在下面,我创建 columns 来保存原始数据,rows 应该保存对 columns 中数据的引用,然后我尝试通过获取 [=] 来更新 columns 16=] 来自 rows 并为其分配一个新值。

use std::collections::HashMap;

#[derive(Debug)]
struct Column {
    name: String,
    data: Vec<i32>,
}
fn main() {
    let mut columns = vec![
        Column {
            name: String::from("col1"),
            data: vec![4, 5, 6],
        },
        Column {
            name: String::from("col2"),
            data: vec![7, 8, 9],
        },
    ];
    println!("{:?}", columns);

    let mut rows = Vec::new();
    let columns_len = columns[0].data.len();
    for i in 0..columns_len {
        let mut row = HashMap::new();
        for column in columns.iter_mut() {
            row.insert(&column.name, column.data.get_mut(i).unwrap());
        }
        rows.push(row);
    }
    println!("{:?}", rows);
    let cell = rows
        .get_mut(1)
        .unwrap()
        .get_mut(&String::from("col2"))
        .unwrap();
    println!("{:?}", cell);
    **cell = 99;
    println!("{:?}", columns);
    println!("{:?}", rows);
    println!("{:?}", cell);
}

很多时候,将可变引用视为独占 引用很有用。也就是说,与其认为它们允许您修改值,不如将它们视为保证这是唯一可以使用该值的 live 引用,并且可变性只是一个很好的副作用。

考虑到这一点,如果您设法获得 Veccolumns 的各个值的可变引用,那么 columns 本身将无法访问(记住,独家访问权)。

并且当您创建 cell 时,它是对 rows 向量的独占引用,那么该向量将在 cell.

的生命周期内不可访问

就是说,只要小心使用迭代器 API(get_mut() 不会这样做是因为编译器无法确保您不会两次使用相同的索引):

    // First create the hash maps
    let mut rows = std::iter::repeat_with(|| HashMap::new())
        .take(columns[0].data.len())
        .collect::<Vec<_>>();
    
    // Then fill in the references.
    for c in columns.iter_mut() {
        for (id, d) in c.data.iter_mut().enumerate() {
            rows[id].insert(c.name.as_str(), d);
        }
    }

请注意,rows 变量的类型为:Vec<HashMap<&str, &mut i32>>,我不知道它是否会有用。

在实际的 Rust 中,很多时候将值的索引存储在 Vec 中而不是对内部值的引用更容易。你可能认为它不是那么高效,但是想想如果你压入vector并且它必须重新分配它的内部内存会发生什么!