如何将可变数组划分为可变子数组

How divide the mutable array into mutable subarrays

提问人:TupleCats 提问时间:12/13/2018 最后编辑:Peter HallTupleCats 更新时间:12/20/2018 访问量:1364

问:

我需要将 mutablearray 划分为 3 个具有可变元素的 mutablesubarray。

#[derive(Debug)]
struct Server {
    time: i64
}


impl Server {
    fn new(x: i64) -> Server {
        return Server {
            time: x
        }
    } 
}

fn main() {
      let mut arr = Vec::<Server>::new();
      arr.push(Server::new(10));
      arr.push(Server::new(20));
      arr.push(Server::new(30));
      arr.push(Server::new(40));
      arr.push(Server::new(50));

      let mut arr1 = arr.iter_mut().filter(|x| x.time > 20).collect::<Vec<&mut Server>>();
      let mut arr2 = arr.iter_mut().filter(|x| x.time < 20).collect::<Vec<&mut Server>>();
      let mut arr3 = arr.iter_mut().filter(|x| x.time == 20).collect::<Vec<&mut Server>>();
}

接下来,对每个子阵列执行不影响主阵列的不同操作。(例如,首先对每个子数组进行排序,而不会影响主数组的顺序。下一步是在每个子数组上操作其元素。这些变化应该反映在主数组的元素中)。

目前,在编译时划分数组 Rust 时,它给出了以下错误:

error[E0499]: cannot borrow `arr` as mutable more than once at a time
  --> src/main.rs:26:18
   |
25 |   let mut arr1 = arr.iter_mut().filter(|x| x.time > 20).collect::<Vec<&mut Server>>();
   |                  --- first mutable borrow occurs here
26 |   let mut arr2 = arr.iter_mut().filter(|x| x.time < 20).collect::<Vec<&mut Server>>();
   |                  ^^^ second mutable borrow occurs here
 ...
29 | }
   | - first borrow ends here
error[E0499]: cannot borrow `arr` as mutable more than once at a time
  --> src/main.rs:27:18
   |
25 |   let mut arr1 = arr.iter_mut().filter(|x| x.time > 20).collect::<Vec<&mut Server>>();
   |                  --- first mutable borrow occurs here
26 |   let mut arr2 = arr.iter_mut().filter(|x| x.time < 20).collect::<Vec<&mut Server>>();
27 |   let mut arr3 = arr.iter_mut().filter(|x| x.time == 20).collect::<Vec<&mut Server>>();
   |                  ^^^ second mutable borrow occurs here
28 |   
29 | }
   | - first borrow ends here
阵 列 可变

评论

1赞 Sven Marnach 12/13/2018
最简单的解决方案是使用内部可变性。Vec<RefCell<Server>>
0赞 hellow 12/13/2018
顺便说一句:惯用的 rust 不用作最后语句 (),而只是写(正如您在我的 playground 示例中看到的那样)。returnreturn Server { time: x }Server { time: x }
0赞 Veedrac 12/13/2018
如果您关心速度,请手动执行此操作,并且可能就地执行此操作。
0赞 hellow 12/13/2018
在这种情况下,“就地”@Veedrac没有任何意义,因为您需要一秒钟来存储其他元素。(只是一个奇怪的问题:你熟悉生锈吗?此外,分区的实现非常简单,并且在不使用花哨的东西的情况下是最容易实现的解决方案。vecunsafe
0赞 Veedrac 12/14/2018
@hellow 您可以就地进行分区,然后处理向量的子切片。像 itertools::p artition 一样,但是一个 3 路分区。[T]::swap 使使用安全代码进行有效分区成为可能。是的,我熟悉 Rust。

答:

3赞 hellow 12/13/2018 #1

您可以使用 Iterator::p artition 将 S 拆分为两个不同的元素,而无需克隆内部元素。 因为你想要三个不同的拆分,所以你必须使用两次(顺序无关紧要)。vecvecpartition

const THRESHOLD: i64 = 20;

let mut arr = Vec::<Server>::new();
arr.push(Server::new(10));
arr.push(Server::new(20));
arr.push(Server::new(30));
arr.push(Server::new(40));
arr.push(Server::new(50));

let (greater, rest): (Vec<_>, Vec<_>) = arr.into_iter().partition(|s| s.time > THRESHOLD);
let (equal, less): (Vec<_>, Vec<_>) = rest.into_iter().partition(|s| s.time == THRESHOLD);

(操场)

因为 Vectors ,并且拥有相应的元素,所以您可以对它们进行可变访问。greaterequalless

评论

0赞 hellow 12/13/2018
作为代码的注释:我建议使用 vec! 宏,而不是乏味的 ,例如pushlet arr = vec![Server::new(10), Server::new(20), Server::new(30), Server::new(40), Server::new(50)];
1赞 Jmb 12/14/2018
但请注意,此答案将项目移动到迭代器中,因此它没有涵盖问题的最后一部分:这些更改应反映在主数组的元素中。
0赞 hellow 12/14/2018
@Jmb你是对的,但恐怕除了使用和一个简单的这是不可能的。我的解决方案显示了(恕我直言)如何处理此问题的最佳解决方案。为了反映对“主数组”的更改,我将再次将所有三个数组收集到一个数组中。RefCellsfilter
0赞 TupleCats 12/14/2018
@hellow 我认为这个决定是错误的:为了反映对“主数组”的更改,我将再次将所有三个数组收集到一个数组中。因为我写过每个子数组都可以排序。也许唯一正确的方法是使用 和RefCellsfilter
1赞 Boiethios 12/14/2018
let mut arr: Vec<_> = vec![10, 20, 30, 40, 50].into_iter().map(Server::new).collect();也很酷。