rust - How to partition Vec in place in method that doesn't own `self`? -
so, there's struct looks this:
struct foo { alpha: vec<t>, beta: vec<t>, }
and method should move values matches condition alpha
beta
. question is: clean way without owning self
?
the vec::partition()
method can't used because moving of self.alpha
causes cannot move out of dereference of &mut-pointer
compile error.
ps: t
have file
inside doesn't implement clone
.
do want drop beta
? sort of thing std::mem::replace
for, allowing pull out:
use std::mem; impl foo { fn munge(&mut self) { let alpha = mem::replace(&mut self.alpha, vec::new()); let (alpha, beta) = alpha.partition(…); self.alpha = alpha; self.beta = beta; } }
note there is new vec
created there briefly, doesn’t matter; doesn’t involve allocation , cheap. (the alternative leaving uninitialised memory there , replacing again, forgetting uninitialised memory, unsafe if partition can fail run destructor on uninitialised memory.)
since want shift elements matching predicate, it’s worth looking @ how partition
implemented:
pub fn partition<f>(self, mut f: f) -> (vec<t>, vec<t>) f: fnmut(&t) -> bool { let mut lefts = vec::new(); let mut rights = vec::new(); elt in self.into_iter() { if f(&elt) { lefts.push(elt); } else { rights.push(elt); } } (lefts, rights) }
knowing how implemented makes implementing doesn’t involve second vector being created rather easy; here’s general idea:
let source = mem::replace(&mut self.alpha, vec::new()); element in source.into_iter() { if f(&element) { /* `f` */ self.alpha.push(element) } else { self.beta.push(element) } }
really, mem::replace
thing need know these sorts of things; rest becomes easy.
Comments
Post a Comment