2017-12-29 30 views
1

Lassen Sie uns sagen, ich habe Vektoren der Primzahlen und Befugnisse:Wie passe ich zu einem Muster wie `& (& usize, & u32)`?

let mut primes: Vec<usize> = ...; 
let mut powers: Vec<u32> = ...; 

Es ist eine Tatsache, dass primes.len() == powers.len().

Ich mag den Benutzer eine Liste von Primzahlen zurückzukehren, die einen entsprechenden Leistungswert von 0 haben (dieser Code richtigen Refs und derefs fehlt):

primes.iter().zip(powers) 
    .filter(|(p, power)| power > 0) 
    .map(|(p, power)| p) 
    .collect::<Vec<usize>>() 

Der Compiler viel beschwert, wie du dir vorstellen kannst. Insbesondere empfängt die filter Argumente vom Typ &(&usize, &u32), aber ich bin nicht korrekt in der Mustererkennung de-referenziert. Ich habe verschiedene Muster ausprobiert, die der Compiler suggeriert (z. B. &(&p, &power), was für mich am sinnvollsten ist), aber ohne Glück. Wie führe ich den Mustervergleich korrekt aus, damit ich den power > 0 Vergleich ohne Problem durchführen kann, und damit ich am Ende eine Vec<usize> sammeln kann?

Antwort

2
primes.iter().zip(powers) 

iter() Iterierten Bezug genommen wird, so erhalten Sie &usize Elemente für Primzahlen. OTOH .zip() ruft .into_iter() auf, die eigene Werte iteriert, also sind Potenzen u32, und diese Iteratoren kombiniert iterieren über (&usize, u32). Technisch gesehen ist nichts falsch daran, über einen solchen gemischten Typ zu iterieren, aber die Inkonsistenz kann verwirrend sein. Sie können .into_iter() oder .iter().cloned() auf Primzahlen verwenden, um die Referenz zu vermeiden, oder .zip(powers.iter()) aufrufen, um beide als Referenzen zu erhalten.

Die zweite Sache ist, dass .filter() Artikel von Referenz &(_,_) nimmt (da es nur bei ihnen „schaut“) und .map() von Besitz Wert (_,_) (die sie es ändern können und zurück).

Für kleine Werte wie ganze Zahlen, Sie in der Regel diese Methoden wie diese verwenden würde:

.filter(|&item| …) 
.map(|item| …) 

Beachten Sie, dass die Syntax in Schließungen ist |pattern: type|, so in dem obigen Beispiel &item entspricht:

.filter(|by_ref| { 
    let item = *by_ref; 
}) 
1

das funktioniert:

fn main() { 
    let primes: Vec<usize> = vec![2, 3, 5, 7]; 
    let powers: Vec<u32> = vec![2, 2, 2, 2]; 

    let ret = primes.iter().zip(powers.iter()) 
      .filter_map(|(p, pow)| { // both are refs, so we need to deref 
       if *pow > 0 { 
        Some(*p) 
       } else { 
        None 
       } 
      }) 
      .collect::<Vec<usize>>(); 

    println!("{:?}", ret); 
} 

Bitte beachte, dass ich verwendet powers.iter() auch die Elemente durch Bezugnahme ergibt. Sie könnten auch cloned() für beide Iteratoren verwenden und mit Werten arbeiten.

Verwandte Themen