比较列表中的所有元素并获取匹配对的可变引用
Compare all elements in list and get mutable references for matching pairs
我的目标是根据某些标准将列表中的每个元素与列表中的每个其他元素进行比较。在伪代码中,类似于:
for i, x in list.enumerate():
for y in list[i..]:
if x.match(y):
// Modify both x and y
我想获得对每个匹配对中的两个项目的可变引用。这被证明是困难的。根据, the best way to get mutable references to multiple items in a list is through split_at_mut。我写了一个包装函数来提取两个对列表的可变引用:
/// Gets two mutable references to elements i and j in list
fn get_pair<'a, T>(i: usize, j: usize, list: &'a mut [T]) -> (&'a mut T, &'a mut T) {
let (a, b) = list.split_at_mut(j);
let first = &mut a[i];
let second = &mut b[0];
(first, second)
}
但是,我仍然无法在不违反借用规则的情况下在嵌套 for 循环中使用此函数:
for stuff1 in list.iter() {
// immutable borrow on list here
for stuff2 in list[i..].iter() {
if stuff1.compare(stuff2) {
let (stuff1, stuff2) = get_pair(i, j, list); // mutable borrow on list
do_something(stuff1, stuff2);
}
}
}
相反,我保存了一对匹配的索引,然后在不同的循环中实际获取元素并对它们进行处理。
// Find matching pairs and push their indices
let mut matches: Vec<(usize, usize)> = Vec::new();
for (i, stuff1) in list.iter().enumerate() {
for (j, stuff2) in list[i..].iter().enumerate() {
if stuff1.compare(stuff2) {
matches.push((i, j));
}
}
}
// Get two mutable references by indices from list
for m in matches.iter() {
let (i, j) = m;
let (stuff1, stuff2) = get_pair(*i, *j, list);
do_something(stuff1, stuff2);
}
这可行,但似乎有点过于复杂。在不违反借用规则的情况下,是否有更简单或更简单的方法来实现?
理想情况下,我想修改原始循环中的匹配对,而不需要单独的循环来遍历索引。
可以在 playground.
上找到我当前代码的完整示例
你可以这样做,它会生成相当不错的代码:
let mut list = [1, 2, 3];
for i in 0..list.len() {
let (a, b) = list.split_at_mut(i);
let item_b = &mut b[0];
for item_a in a {
println!("{} {}", item_a, item_b);
}
}
这里的关键是 0..len
迭代避免将 list
锁定为只读。 split_at_mut
向借用检查器证明两个引用不能指向同一个元素。
我的目标是根据某些标准将列表中的每个元素与列表中的每个其他元素进行比较。在伪代码中,类似于:
for i, x in list.enumerate():
for y in list[i..]:
if x.match(y):
// Modify both x and y
我想获得对每个匹配对中的两个项目的可变引用。这被证明是困难的。根据
/// Gets two mutable references to elements i and j in list
fn get_pair<'a, T>(i: usize, j: usize, list: &'a mut [T]) -> (&'a mut T, &'a mut T) {
let (a, b) = list.split_at_mut(j);
let first = &mut a[i];
let second = &mut b[0];
(first, second)
}
但是,我仍然无法在不违反借用规则的情况下在嵌套 for 循环中使用此函数:
for stuff1 in list.iter() {
// immutable borrow on list here
for stuff2 in list[i..].iter() {
if stuff1.compare(stuff2) {
let (stuff1, stuff2) = get_pair(i, j, list); // mutable borrow on list
do_something(stuff1, stuff2);
}
}
}
相反,我保存了一对匹配的索引,然后在不同的循环中实际获取元素并对它们进行处理。
// Find matching pairs and push their indices
let mut matches: Vec<(usize, usize)> = Vec::new();
for (i, stuff1) in list.iter().enumerate() {
for (j, stuff2) in list[i..].iter().enumerate() {
if stuff1.compare(stuff2) {
matches.push((i, j));
}
}
}
// Get two mutable references by indices from list
for m in matches.iter() {
let (i, j) = m;
let (stuff1, stuff2) = get_pair(*i, *j, list);
do_something(stuff1, stuff2);
}
这可行,但似乎有点过于复杂。在不违反借用规则的情况下,是否有更简单或更简单的方法来实现?
理想情况下,我想修改原始循环中的匹配对,而不需要单独的循环来遍历索引。
可以在 playground.
上找到我当前代码的完整示例你可以这样做,它会生成相当不错的代码:
let mut list = [1, 2, 3];
for i in 0..list.len() {
let (a, b) = list.split_at_mut(i);
let item_b = &mut b[0];
for item_a in a {
println!("{} {}", item_a, item_b);
}
}
这里的关键是 0..len
迭代避免将 list
锁定为只读。 split_at_mut
向借用检查器证明两个引用不能指向同一个元素。