2017-10-02 1 views
-1

par paires j'écrire du code problème pour une fonction qui prend un itérateur et retourne un itérateur qui itère par paires (Option<T>, T) comme siMettre en œuvre un 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()) 
    |       ^^^^ 
    | 

Je ne sais pas pourquoi xs n'est pas itérable. Je l'ai déclaré dans la clause where n'ai-je pas?

+0

'.iter()' est pour créer un itérateur, mais vous en avez déjà un. 'xs' est déjà un' Iterator'. – loganfsmyth

+0

@loganfsmyth Oh, d'accord. Quel est le type pour quelque chose qui a la méthode '.iter()'? – user1685095

+0

Je ne crois pas qu'il y en ait un. Il y a cependant un 'IntoIterator' qui définit la méthode' into_iter() '. Ceci est automatiquement implémenté pour tous les 'Iterator's, donc si vous avez une API qui prend' IntoIterator' et que vous ne voulez pas consommer réellement l'argument, l'appelant peut simplement appeler '.iter()' lui-même et passer l'itérateur résultant. –

Répondre

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

Cela n'a pas de sens. Voir What is the correct way to return an Iterator? et What is the difference between `e1` and `&e2` when used as the for-loop variable?.

I: Iterator<Item = T>, 

Il n'y a aucune raison de préciser que le Item est un T.

[None].iter() 

Il est préférable d'utiliser iter::once.

xs.iter() 

Il n'y a pas trait dans la bibliothèque standard qui définit une méthode iter. Peut-être que vous vouliez dire IntoIterator?

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

Il n'y a aucune raison de préciser le type ici; i32 est le type intégral par défaut.

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

Ce n'est pas un type valide pour Vec et votre forme originale ne dispose même pas des symboles équilibrés.


Après tout cela, vous êtes confrontés à des choix difficiles. Votre exemple de code passe dans un itérateur qui a références à la tranche, mais vous avez écrit votre assertion de sorte que vous vous attendez à récupérer les non-références. Vous avez également tenté d'utiliser un itérateur arbitraire deux fois. il n'y a aucune garantie qu'une telle chose soit viable.

La forme la plus générique que je vois est:

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)]); 
} 

Voir aussi:

+0

Merci beaucoup. Je pense que je ne comprends pas une seule chose. Pourquoi 'Box' est-il nécessaire ici? – user1685095

+1

@ user1685095 La question liée ["Quelle est la bonne façon de retourner un Iterator?"] (Https://stackoverflow.com/questions/27535289/what-is-the-correct-way-to-return-an-iterator) répond à cette question. –