Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How can I split a vector into two halfs in rust?

I have a vector Vec<Box<dyn SomeTrait>>, because I want to split it into many pieces in a recursive function, I need to split one vector into two half parts each time.

Is there a way that can split a vector like this at some index without allocating new memory?

As Box<dyn SomeTrait> doesn’t have Copy or Clone trait, I guess when splited, the owner of the vector would be changed.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Is there a way that can split a vector like this at some index without allocating new memory?

It looks like you need some views (i.e. slices) on the existing vector.
Creating another vector holding some elements from the original one will require a new memory allocation: the heap storage for the elements of the second vector (the boxes themselves, not the objects these boxes point to, these latter won’t move).

Here is a trivial example in which regular slices taken from the original vector will be problematic (exclusive and shared reference to the original vector at the same time), and a solution using split_at_mut().

Splitting each sub-part recursively (for your specific program) will always refer to the original storage of the initial vector, without any new dynamic allocation.

trait SomeTrait: std::fmt::Debug {
    fn get_something(&self) -> &str;
    fn change_something(
        &mut self,
        txt: &str,
    );
}

#[derive(Debug)]
struct SomeStruct {
    text: String,
}

impl SomeTrait for SomeStruct {
    fn get_something(&self) -> &str {
        self.text.as_str()
    }
    fn change_something(
        &mut self,
        txt: &str,
    ) {
        self.text.push_str(txt);
    }
}

fn some_function(
    head: &[Box<dyn SomeTrait>],
    tail: &mut [Box<dyn SomeTrait>],
) {
    tail.iter_mut().for_each(|elem| {
        if let Some(pos) = head
            .iter()
            .position(|e| e.get_something() == elem.get_something())
        {
            elem.change_something(&format!(" found at {}", pos));
        }
    });
}

fn main() {
    let mut v: Vec<Box<dyn SomeTrait>> = Vec::new();
    for i in 0..6 {
        v.push(Box::new(SomeStruct {
            text: format!("text {}", i % 3),
        }))
    }
    let mid = v.len() / 2;
    //
    // some_function(&v[0..mid], &mut v[mid..]); // error!
    //
    let (head, tail) = v.split_at_mut(mid);
    some_function(head, tail);
    //
    println!("{:#?}", v);
}
/*
[
    SomeStruct {
        text: "text 0",
    },
    SomeStruct {
        text: "text 1",
    },
    SomeStruct {
        text: "text 2",
    },
    SomeStruct {
        text: "text 0 found at 0",
    },
    SomeStruct {
        text: "text 1 found at 1",
    },
    SomeStruct {
        text: "text 2 found at 2",
    },
]
*/
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading