重复删除列表列表与借用检查器冲突

Deduping a list of lists runs afoul of the Borrow Checker

我正在尝试对列表列表进行重复数据删除。我已经有一个程序可以毫无问题地删除单个列表的重复数据。但是,现在我想同时连接多个列表和重复数据删除,并且借用检查器正在使用它的老把戏。

在下面的代码中,唯一需要知道的关于 FeelValue 的重要信息是它是 Clone 而不是 Copy。关键目标是仅通过一次克隆调用即可完成串联和重复数据删除。最终结果是 return 到 deduped Vec,它必须具有稳定的顺序。通过两次克隆调用很容易做到这一点:只需将 set.insert(&item) 更改为 set.insert(item.clone()) 并更改 HashSet 的类型。

如果需要,我很乐意排干或弄乱 RefCell 中的 Vec

let mut list_vecs: Vec< Rc<RefCell<Vec<FeelValue>>> > = Vec::new();

// Do something to fill up list_vecs...
// .....SNIP.....

let mut deduped: Vec<FeelValue> = Vec::new();
let mut set: HashSet<&FeelValue> = HashSet::new();
for rr_vec in list_vecs.iter() {
  let rr_vec_b = rr_vec.borrow();
  for item in rr_vec_b.iter() {
    if set.insert(&item) {
      deduped.push(item.clone());
    }
  }          
}

错误是:

`rr_vec_b` does not live long enough

borrowed value does not live long enoughrustc(E0597)

这是一个类似的例程,它成功地删除了单个列表的重复数据。 下面list的定义是:list: &Vec<FeelValue>

|list| { 
  let mut set: HashSet<&FeelValue> = HashSet::with_capacity(list.len());
  let deduped: Vec<FeelValue> = list
    .iter()
    .filter(|item| set.insert(item))
    .cloned()
    .collect();
  FeelValue::new_list(deduped) 
}

我只是想不出一种方法来将列表的列表链接到一个迭代器中,或者我可能会使用相同的方法。

您的问题不在于借用检查器本身,而在于RefCell。从 borrow() 返回的 Ref 必须 在从它派生的任何引用的持续时间内保持在范围内。

一个技巧是将所有 RefCell 中的 Ref 收集到 Vec 中,以便在遍历引用时所有内容都在范围内:

let list_vecs: Vec<Rc<RefCell<Vec<FeelValue>>>> = Vec::new();
let list_vec_refs: Vec<Ref<Vec<FeelValue>>> = list_vecs.iter().map(|v| v.borrow()).collect();

let mut deduped: Vec<FeelValue> = Vec::new();
let mut set: HashSet<&FeelValue> = HashSet::new();
for rr_vec in list_vec_refs.iter() {
    for item in rr_vec.iter() {
        if set.insert(&item) {
            deduped.push(item.clone());
        }
    } 
}

查看它在 playground 上的工作情况。