2016-05-08 3 views
1

verbraucht Ich habe die folgende Funktion, die einen Vektor als Argument verwendet und einen Vektor der Paare von Elementen:Alternative zu Vec :: Brocken(), die den Vektor

fn to_pairs(flat: Vec<u64>) -> Vec<(u64, u64)> { 
    assert!(flat.len() % 2 == 0); 
    let mut pairs = Vec::new(); 
    pairs.reserve(flat.len()/2); 
    for pair in flat.chunks(2) { 
     assert!(pair.len() == 2); 
     pairs.push((pair.get(0).unwrap().clone(), pair.get(1).unwrap().clone())); 
    } 
    pairs 
} 

ich den Vektor verbrauchen wollen flat also muss ich seine Elemente nicht klonen, wenn ich das Paar konstruiere. Ist es möglich, eine Variation von Vec::chunks() selbst nicht erneut zu implementieren?

+0

Haben Sie 'unsafe' verwenden? – kennytm

+1

würde ich lieber nicht. –

+0

Ist es geeignet, wenn Sie andere Strukturen wie [numeric :: Tensor] (http://numeric.rs/doc/numeric/tensor/struct.Tensor.html) verwenden, die das Umformen unterstützt? – kennytm

Antwort

0

Ich möchte den Vektor flat konsumieren, also muss ich seine Elemente nicht klonen, wenn ich das Paar erstelle.

Konvertieren Sie die Eingabe Vec in einen Iterator, und nehmen Sie dann jeweils zwei Dinge aus dem Iterator. Im Wesentlichen wollen Sie das gleiche wie processing a Range (an iterator) in chunks:

fn to_pairs<T>(flat: Vec<T>) -> Vec<(T, T)> { 
    let len = flat.len(); 

    assert!(len % 2 == 0); 
    let mut pairs = Vec::with_capacity(len/2); 

    let mut input = flat.into_iter().peekable(); 

    while input.peek().is_some() { 
     match (input.next(), input.next()) { 
      (Some(a), Some(b)) => pairs.push((a, b)), 
      _ => unreachable!("Cannot have an odd number of values"), 
     } 
    } 

    pairs 
} 

fn main() { 
    assert_eq!(vec![(1,2), (3,4)], to_pairs(vec![1,2,3,4])); 
    assert_eq!(vec![(true,true), (false,false)], to_pairs(vec![true,true,false,false])); 
} 

Die assert!(len % 2 == 0); hier sehr wichtig ist, da Iterator keine Garantien über dem macht, was geschieht nach das erste Mal next kehrt None. Da wir next zweimal aufrufen, ohne den ersten Wert zu überprüfen, könnten wir diesen Fall auslösen. In anderen Fällen möchten Sie fuse verwenden.

Als pointed out by Kha, könnten Sie die while Schleife ein wenig vereinfachen:

let mut input = flat.into_iter(); 

while let (Some(a), Some(b)) = (input.next(), input.next()) { 
    pairs.push((a, b)); 
} 
+1

Sie könnten "peek" durch einen '(None, None)' -Fall ersetzen –