Iterator vs IntoIterator für Abflachung
Ich spiele mit Iteratoren herum und habe verwendet, Flattenum besser zu verstehen, wie Iteratoren funktionieren. Dieses Beispiel:
assert_eq!(vec![1, 2].iter().flatten().count(), 2);
Kompiliert nicht und gibt den Fehler an (auch der Hauptfehler):
error[E0277]: `&{integer}` is not an iterator
--> src/lib.rs:59:38
|
59 | assert_eq!(vec![1, 2].iter().flatten().count(), 2);
| ^^^^^^^ `&{integer}` is not an iterator
|
= help: the trait `std::iter::Iterator` is not implemented for `&{integer}`
= note: required because of the requirements on the impl of `std::iter::IntoIterator` for `&{integer}`
Was mich verwirrt ist, dass es so aussieht, als Flattenmüsste der Verschachtelte Itemimplementiert werden IntoIterator. Ich habe dies in den Rustdocs bestätigt, wo sie erklären
pub struct Flatten<I>
where
I: Iterator,
<I as Iterator>::Item: IntoIterator
IntoIterator bietet nur eine Möglichkeit, um zu definieren, wie ein Typ in einen Iterator konvertiert wird. Warum konnte das Merkmal nicht gebunden sein <I as Iterator>::Item: Iterator? Wenn das verschachtelte Element implementiert wird Iterator, erhalten wir sicherlich dasselbe, Flattenda die verschachtelten Elemente selbst Iteratoren sein müssen. Welchen Unterschied / Nutzen bringt es IntoIteratorstattdessen zu nutzen ?
Antworten
Wenn Sie eine Sammlung von Sammlungen zusätzlich zu einer Sammlung von Iteratoren IntoIteratoreher benötigen als reduzieren können Iterator.
Der Auflistungstyp Vecunterscheidet sich beispielsweise vom Iteratortyp. Wenn also flattendie Elemente Iterators sein müssen, können Sie a Vecvon Vecs nicht reduzieren .
IntoIteratorstellt einen Typ dar, der in einen Iterator konvertiert werden kann , z. B. eine Vecoder viele andere Sammlungen (oder einen Iterator!). Das funktioniert zum Beispiel:
fn main() {
let nested_vec: Vec<Vec<i32>> = vec![vec![1, 2], vec![3, 4]];
let flat_vec: Vec<i32> = nested_vec.into_iter().flatten().collect();
println!("{:?}", flat_vec);
}
Sie können dieses Beispiel auf dem Spielplatz ausprobieren . Wenn Sie into_iter()oben anstelle von verwenden, stellen Sie iter()sicher, dass wir über i32s iterieren und nicht auf s verweiseni32 . (Danke Cerberus für den Vorschlag into_iter()statt copied().)
(Weitere Typen mit IntoIteratorImplementierungen finden Sie im Abschnitt "Implementierungen für fremde Typen" in den Dokumenten .)