J'ai une Vec<(String, i64)>
et avez besoin de itérer sur le String
s et les déplacer, puis itérer sur le i64
s.
Cependant, si je déplace le String
s, je dois stocker le i64
Encore une fois dans un autre Vec
:
let l: Vec<_> = l
.into_iter()
.map(|(string, int)| {
drop(string);
int
})
.collect();
for i in l {
process(i);
}
Comment puis-je itération sur le String
s et i64
s séparément sans engendrer de performances supplémentaires.
La seule solution que je puisse penser à l'heure actuelle qui ne causera pas d'opérations supplémentaires consiste à stocker les String
s et i64
s séparément.
Vous pouvez utiliser std::mem::take()
en itérant sur le Vec
dans une première passe pour prendre la propriété de l'élément String
tout en mettant un _ non-alloué Default
à sa place. Cela vous permet de conserver le Vec
sous sa forme d'origine, aucun conteneur supplémentaire n'est requis.
fn foo(mut inp: Vec<(String, i64)>) {
// First pass over the Vec "extracts" the owned Strings, replacing the content
// in the Vec by a non-allocating empty String, which is close to zero cost;
// this leaves the Vec as is, so no intermediate representation is needed.
for s in inp.iter_mut().map(|(s, _)| std::mem::take(s)) {
// Process String
}
// Something happens
// Second pass ignores the empty strings, processes the integers
for i in inp.into_iter().map(|(_, i)| i) {
// Process the integers
}
}
Si le type de liste peut être changé en Vec<Option<String>, i64>
à partir de Vec<String, i64>
, alors vous pouvez essayer de la manière suivante.
fn main() {
let mut l = Vec::new();
l.Push((Some("a".to_string()), 1i64));
l.Push((Some("b".to_string()), 2));
l.Push((Some("c".to_string()), 3));
l.Push((Some("d".to_string()), 4));
l.iter_mut().for_each(|(s, _)| {
if let Some(x) = s.take() {
println!("Processing string: {}", x);
}
});
l.iter().for_each(|(_, i)| {
println!("Processing int: {}", i);
});
}
Utilisez unzip
pour les séparer:
fn main(){
let original = vec![("a", 1), ("b", 2)];
let (s, i): (Vec<_>, Vec<_>) = original.into_iter().unzip();
for a in s {
println!("{}", a);
}
for b in i {
println!("{}", b);
}
}