2017-12-10 21 views
3

저는 언어를 배우는 방법으로 올해 녹의 강림 대원을 찾으려고합니다. 나는 다음과 같은 구조로 (7 일)에서 입력을 구문 분석했습니다동시에 녹 HashMap을 반복하고 그 값 중 일부를 수정할 수 있습니까?

struct Process { 
    name: String, 
    weight: u32, 
    children: Vec<String>, 
    parent: Option<String> 
} 

이들은 HashMap<String, Process>에 저장됩니다. 이제 부모의 "children"벡터에서 찾은 것을 기반으로지도의 값을 반복하고 부모 값을 업데이트하려고합니다. 작동하지 않습니다 무엇

for p in self.processes.values() { 
    for child_name in p.children { 
     let mut child = self.processes.get_mut(child_name).expect("Child not found."); 
     child.parent = p.name; 
    } 
} 

내가 HashMap (self.processes)로 변경 가능한 참조 및 비 변경 가능한 참조, 또는 두 개의 가변 참조 모두를 가질 수있다.

그래서 Rust에서이 작업을 수행하는 가장 관용적 인 방법은 무엇입니까? 내가 볼 수있는 두 가지 옵션은 다음과 같습니다

  1. 복사 상위/하위 한 번에 새 임시 데이터 구조에 관계하고, 불변의 참조가 범위를 벗어난 후 다음 두 번째 패스에서 프로세스 구조체를 업데이트합니다.
  2. 내 데이터 구조를 변경하여 "Hash"를 자체 HashMap에 넣습니다.

세 번째 옵션이 있습니까?

+0

'self.processes'는'HashMap '입니다. – Stefan

+1

나는'Vec '로 가서 다른 항목에 대한 참조로'usize'를 사용합니다. 2 패스 접근법을 사용할 수 있습니다 : 두 번째 패스 fill'children'과'parent'에서'HashMap '를 만들고'name' +'weight'를 채 웁니다. 많은 가능성 :) – Stefan

+0

@Stefan : meh, 나는 불완전한 코드로 작업하는 것을 좋아하지 않는다. 그래도 추론하는 것은 괜찮은 질문 인 것 같습니다. – ljedrz

답변

4

예, RefCell를 사용하여 HashMap의 값으로 내부 가변성을 부여 할 수 있습니다 : 아이가 이미 borrow로 빌린 경우

struct ProcessTree { 
    processes: HashMap<String, RefCell<Process>>, // change #1 
} 

impl ProcessTree { 
    fn update_parents(&self) { 
     for p in self.processes.values() { 
      let p = p.borrow();     // change #2 
      for child_name in &p.children { 
       let mut child = self.processes 
        .get(child_name)    // change #3 
        .expect("Child not found.") 
        .borrow_mut();     // change #4 
       child.parent = Some(p.name.clone()); 
      } 
     } 
    } 
} 

borrow_mut 런타임에 당황한다. 이것은 프로세스가 자신의 부모 인 경우에 발생합니다 (아마도 발생하지 않아야하지만보다 강력한 프로그램에서는 당황하지 말고 의미있는 오류 메시지를 표시하려고합니다).

나는이 코드를 컴파일하기 위해 몇 가지 이름을 고안하여 약간 변경했다. 특히 p.name.clone()p.name의 전체 복사본을 만듭니다. nameparent은 모두 String이므로 소유하고 있어야합니다.