2017-10-02 2 views
-1

ich Schwierigkeiten haben, einen Funktionscode zu schreiben, die einen Iterator nimmt und gibt einen Iterator, dass in Iterierten Paare (Option<T>, T) wie soImplementieren Sie eine paarweise Iterator

a = [1,2,3] 
assert pairwise(a) == `[(None, 1), (Some(1), 2), (Some(2), 3)] 
fn pairwise<I, T>(&xs: &I) -> I 
where 
    I: Iterator<Item = T>, 
{ 
    [None].iter().chain(xs.iter().map(Some)).zip(xs.iter()) 
} 

fn main() { 
    let data: Vec<i32> = vec![1, 2, 3]; 
    let newdata: Vec<Option<i32>, i32> = pairwise(&data).collect(); 
    println!("{:?}", newdata); 
} 
error[E0599]: no method named `iter` found for type `I` in the current scope 
--> src/main.rs:3:28 
    | 
3 |  [None].iter().chain(xs.iter().map(Some)).zip(xs.iter()) 
    |       ^^^^ 
    | 

nicht sicher, warum xs nicht ist iterierbar. Ich habe es in der where Klausel angegeben habe ich nicht?

+0

'.iter()' ist zum Erstellen eines Iterators, aber Sie haben bereits einen. 'xs' ist bereits ein' Iterator'. – loganfsmyth

+0

@loganfsmyth Oh, okay. Was ist der Typ für etwas, das '.iter()' Methode hat? – user1685095

+0

Ich glaube nicht, dass es einen gibt. Es gibt jedoch einen 'IntoIterator', der die' into_iter() 'Methode definiert. Dies wird automatisch für alle Iteratoren implementiert. Wenn Sie also eine API haben, die einen IntoIterator akzeptiert und Sie das Argument nicht konsumieren wollen, kann der Aufrufer einfach '.iter()' selbst aufrufen und übergeben der resultierende Iterator. –

Antwort

2
fn pairwise<I, T>(&xs: &I) -> I 

Das macht keinen Sinn. Siehe What is the correct way to return an Iterator? und What is the difference between `e1` and `&e2` when used as the for-loop variable?.

I: Iterator<Item = T>, 

Es gibt keinen Grund zu geben, dass die Item ist ein T.

[None].iter() 

Es ist besser iter::once zu verwenden.

xs.iter() 

Es gibt in der Standard-Bibliothek kein Merkmal, das eine iter Methode definiert. Vielleicht meintest du IntoIterator?

let data: Vec<i32> = vec![1, 2, 3] 

Es gibt keinen Grund, hier die Art zu spezifizieren; i32 ist der Standardintegraltyp.

Vec<Option<i32>, i32> 
Vec<Option<i32>, i32>> // original version 

Diese für Vec kein gültiger Typ ist, und Ihre ursprüngliche Form haben nicht einmal ausgeglichen Symbole.


Nach all dem stehen Sie vor schwierigen Entscheidungen. Ihr Beispielcode übergibt einen Iterator mit Referenzen an das Segment, aber Sie haben Ihre Assertion so geschrieben, dass Sie erwarten, dass keine Referenzen zurückkommen. Sie haben auch versucht, einen beliebigen Iterator zweimal zu verwenden. es gibt keine Garantie, dass so etwas möglich ist.

Die allgemeinste Form ich sehe, ist:

use std::iter; 

fn pairwise<'a, I>(xs: I) -> Box<Iterator<Item = (Option<I::Item>, I::Item)> + 'a> 
where 
    I: 'a + IntoIterator + Clone, 
{ 
    let left = iter::once(None).chain(xs.clone().into_iter().map(Some)); 
    let right = xs.into_iter(); 
    Box::new(left.zip(right)) 
} 

fn main() { 
    let data = vec![1, 2, 3]; 

    let newdata: Vec<_> = pairwise(&data).collect(); 
    assert_eq!(newdata, [(None, &1), (Some(&1), &2), (Some(&2), &3)]); 

    let newdata: Vec<_> = pairwise(data.iter().cloned()).collect(); 
    assert_eq!(newdata, [(None, 1), (Some(1), 2), (Some(2), 3)]); 
} 

Siehe auch:

+0

Vielen Dank. Ich denke, ich verstehe nur eine Sache nicht. Warum wird 'Box' hier benötigt? – user1685095

+1

@ user1685095 Die verknüpfte Frage ["Was ist der richtige Weg, um einen Iterator zurückzugeben?"] (Https://stackoverflow.com/questions/27535289/what-is-the-correct-way-to-return-an-iterator) beantwortet diese Frage. –

Verwandte Themen