2017-10-09 1 views
8

Ich versuche, einige Elemente aus einem Vektor, basierend auf einem Prädikat, zu entfernen und das Ergebnis zu sammeln. Hier ist ein (nicht funktioniert) Beispiel mit einem erwarteten Ergebnis:Gibt es eine Möglichkeit, Teile eines Vektors basierend auf einem Prädikat zu entwässern?

let mut v: Vec<i32> = vec![1, 2, 3, 4, 5, 6]; 

let drained: Vec<i32> = v.iter().filter(|e| (*e) % 2 == 0).drain(..).collect(); 

assert_eq!(v, vec![1, 3, 5]); 
assert_eq!(drained, vec![2, 4, 6]); 

Dies führt zu dem Fehler

error[E0599]: no method named `drain` found for type `std::iter::Filter<std::slice::Iter<'_, i32>, [[email protected]/main.rs:4:45: 4:62]>` in the current scope 
--> src/main.rs:4:64 
    | 
4 |  let drained: Vec<i32> = v.iter().filter(|e| (*e) % 2 == 0).drain(..).collect(); 
    |                ^^^^^ 

Es gibt mehrere Alternativen, die ich sah, keiner von ihnen scheint zu tun, was ich will:

  • Vec::retain entfernt die Elemente aus dem Vektor, ist aber nicht das Eigentum an den entfernten Elemente zurück zu geben.

  • v.drain(..).filter(condition).collect() gibt den korrekten Wert für drained zurück, leert jedoch den gesamten Vektor.

+0

Sie haben versucht, das Array mit to_vec zu konvertieren? 'leave drained: Vec = v.iter(). Filter (| e | (* e)% 2 == 0) .to_vec(). Drain (..). Collect();' – aug2uag

Antwort

7

Nicht im stabilen Rost 1.20.0. Es gibt ein instabiles nächtliches Feature namens drain_filter, die genau das tut, was Sie wollen:

#![feature(drain_filter)] 

fn main() { 
    let mut v: Vec<i32> = vec![1, 2, 3, 4, 5, 6]; 

    let drained: Vec<i32> = v.drain_filter(|&mut e| e % 2 == 0).collect(); 

    assert_eq!(v, vec![1, 3, 5]); 
    assert_eq!(drained, vec![2, 4, 6]); 
} 

Als stabiles Problem zu umgehen, können Sie möglicherweise Iterator::partition verwenden, aber es wieder verwendet den Speicher nicht:

fn main() { 
    let v: Vec<i32> = vec![1, 2, 3, 4, 5, 6]; 

    let (drained, v): (Vec<_>, Vec<_>) = v.into_iter().partition(|&e| e % 2 == 0); 

    assert_eq!(v, vec![1, 3, 5]); 
    assert_eq!(drained, vec![2, 4, 6]); 
} 
Verwandte Themen