重复删除列表列表与借用检查器冲突
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 上的工作情况。
我正在尝试对列表列表进行重复数据删除。我已经有一个程序可以毫无问题地删除单个列表的重复数据。但是,现在我想同时连接多个列表和重复数据删除,并且借用检查器正在使用它的老把戏。
在下面的代码中,唯一需要知道的关于 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 上的工作情况。