Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use mutable iterator twice

Tags:

iterator

rust

I'm trying to write a general function that takes an iterable (or iterator) and iterates it twice, at least once mutably, like:

fn f(iter: I)
where I: Iterator<Item = &mut i32> + Clone {
    for i in iter.clone() {
        println!("{}", *i);
    }

    for i in iter.clone() {
        *i += 1;
    }
}

But it doesn't work because mutable iterators tend not to have clone() implemented, and for just reasons. My real world example is iteration over HashMap values, where std::collections::hash_map::ValuesMut is not Clone. Are there any ways to do it?

like image 666
Dekakaruk Avatar asked Mar 27 '26 23:03

Dekakaruk


1 Answers

Unfortunately you are unable to do this. You will either need to merge them into a single for loop or save the items from the iterator to iterate over them again later.

The closest thing I could come up with is to use IntoIterator to require that the argument can be used to make a new iterator multiple times.

pub fn foo<'a, T>(iter: &'a mut T) 
    where for<'b> &'b mut T: IntoIterator<Item=&'a mut i32> {

    for i in iter.into_iter() {
        println!("{}", *i);
    }

    for i in iter.into_iter() {
        *i += 1;
    }
}


let mut map = HashMap::new();
map.insert(2, 5);
map.insert(6, 1);
map.insert(3, 4);
    
foo(&mut map.values_mut())

However, it seems like much less of a headache for you if you just pass a reference to the entire map.

pub fn bar<T>(map: &mut HashMap<T, i32>) {
    for i in map.values() {
        println!("{}", *i);
    }

    for i in map.values_mut() {
        *i += 1;
    }
}
like image 140
Locke Avatar answered Mar 30 '26 12:03

Locke