首页 > 解决方案 > 如何获取 HashMap 中的值以相互引用?

问题描述

我正在尝试通过为COOL编写编译器来自学 Rust 。

我有一个HashMap按名称存储多个节点的。我还希望每个节点都引用其父节点(如果有的话)。这样,我既可以按名称查找节点,也可以在恒定时间内将树从子节点导航到父节点。

在此示例中,我希望命名B为引用的节点A

#![allow(unused_variables)]
#![allow(dead_code)]

use std::collections::HashMap;

struct Node {
    name: String,
    parent_name: Option<String>,
    parent: Option<&'static Node>, // I'm not sure this is the correct lifetime
}

fn main() {
    let mut hm: HashMap<String, Node> = HashMap::new();

    hm.insert(
        "A".to_string(),
        Node {
            name: "A".to_string(),
            parent_name: None,
            parent: None,
        },
    );

    hm.insert(
        "B".to_string(),
        Node {
            name: "B".to_string(),
            parent_name: Some("A".to_string()),
            parent: None,
        },
    );

    // ---------------
    // This is where things go awry.

    let a: &Node = hm.get(&"A".to_string()).unwrap();
    let b: &mut Node = hm.get_mut(&"B".to_string()).unwrap();
    
    b.parent = Some(a);
}

无论我如何更改代码,我都会根据多个引用和/或生命周期问题得到错误。有没有办法在 Rust 中做到这一点?

标签: rust

解决方案


可以使用Rc让父节点同时为 HashMap 和子节点所有,使用RefCell可以让你改变不可变引用的数据,这样你就不必同时借用hm可变和不可变。

#![allow(unused_variables)]
#![allow(dead_code)]

use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;

struct Node {
    name: String,
    parent_name: Option<String>,
    parent: Option<Rc<RefCell<Node>>>, // use Rc to enable multiple ownership
}

fn main() {
    let mut hm: HashMap<String, Rc<RefCell<Node>>> = HashMap::new();

    hm.insert(
        "A".to_string(),
        Rc::new(RefCell::new(Node {
            name: "A".to_string(),
            parent_name: None,
            parent: None,
        })),
    );

    hm.insert(
        "B".to_string(),
        Rc::new(RefCell::new(Node {
            name: "B".to_string(),
            parent_name: Some("A".to_string()),
            parent: None,
        })),
    );



    let a: &Rc<RefCell<Node>> = hm.get(&"A".to_string()).unwrap();
    let b: &Rc<RefCell<Node>> = hm.get(&"B".to_string()).unwrap();  
    // Can't borrow hm as mutable and immutable at the same time
    // use RefCell to mutate data even when there are immutable references to that data
    
    b.borrow_mut().parent = Some(Rc::clone(a));
}

推荐阅读