4

I need to divide the mutablearray into 3 mutablesubarrays with mutable elements.

#[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>>();
}

Next, over each subarray to carry out different manipulations that do not affect the main array. (For example, each subarray is first sorted without affecting the order of the main array. The next step is to manipulate its elements over each subarray. And these changes should be reflected in the elements of the main array).

At the moment, when dividing the array Rust when compiling, it gives the following error:

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
5
  • 1
    The easiest solution is to use interior mutability, Vec<RefCell<Server>>. Commented Dec 13, 2018 at 15:14
  • As a sidenote: Idiomatic rust does not use return as last statement (return Server { time: x }), but instead just write Server { time: x } (as you can see in my playground example). Commented Dec 13, 2018 at 15:18
  • If you care about speed, do this manually and potentially in-place. Commented Dec 13, 2018 at 15:39
  • @Veedrac "in-place" doesn't make any sense in this context, because you need a second vec for storing the other elements. (Just a curious question: are you familar with rust?). Also the implementation of partition is very straight forward and would be the easiest to implement solution without using fancy unsafe stuff. Commented Dec 13, 2018 at 15:55
  • @hellow You can partition in place and then work over subslices of your vector. Like itertools::partition but a 3-way partition. [T]::swap makes it possible to partition efficiently with safe code. Yes I am familiar with Rust. Commented Dec 13, 2018 at 22:16

1 Answer 1

3

You can use Iterator::partition to split up your vec into two distinct vecs without cloning the inner elements. Because you want three different splits, you have to use partition twice (the order doesn't matter).

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);

(playground)

Because the Vectors greater, equal and less own the corresponding elements, you have mutable access to them.

Sign up to request clarification or add additional context in comments.

6 Comments

As a note to the code: I would suggest using the vec! macro, instead of the tedious push, e.g. let arr = vec![Server::new(10), Server::new(20), Server::new(30), Server::new(40), Server::new(50)];
Note however that this answer moves the items into the iterators, so it doesn't cover the last part of the question: these changes should be reflected in the elements of the main array.
@Jmb you're right, but I'm afraid apart from using RefCells and a simple filter this isn't possible. My solution shows the (IMHO) best solution how to deal with this problem. To reflect the changes to the 'main array' I would just collect all three arrays into one again.
@hellow I think this decision is wrong: To reflect the changes to the 'main array' I would just collect all three arrays into one again. Because i wrote that each subarray can be sorted. Maybe the only right way is to use RefCells and filter
let mut arr: Vec<_> = vec![10, 20, 30, 40, 50].into_iter().map(Server::new).collect(); is cool too.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.