Return iterator of indeterminate length

I'm trying to add a 4 neighbours iterator to a Vec.

How do I make an iterator that contains 1 or more elements that can be non-contiguously indexed in the vector?

I'm poking at it with something like this, but nobody is very happy with this:

pub fn iter_four_neighbors(&self, row: usize, col: usize) -> Empty<&T> {
        if row < self.rows && col < self.cols {
            let i = iter::empty::<&T>();

            if row > 0 { // N
                // i.chain(iter::once(*self.get(row-1, col).unwrap()));
                let b = &self.data[row * self.cols + col];

                i.chain(iter::once(b));
            }

Alos I think there was a grid class that implemented 4 and 8 neighbours (so I could look how they did it), but I can't quite find it at the moment.

Here's one way.

    fn neighbors(&self, row: usize, col: usize) -> [Option<&T>; 4] {
        if row < self.rows && col < self.cols {
            // ... test boundary conditions to build array ...
        } else {
            [None; 4]
        }
    }

    fn iter_neighbors(&self, row: usize, col: usize) -> impl Iterator<Item=&T> {
        self.neighbors(row, col).into_iter().flatten()
    }
1 Like

Oh sorry, I should read the whole thing!

There's also something like

fn neighbors(x: usize, y: usize) -> impl Iterator<Item=usize> {
    let rows = 4; let cols = 4;
    (if x == 0 { None } else { Some((x - 1, y)) }).into_iter()
        .chain(if x == cols - 1 { None } else { Some((x + 1, y)) })
        .chain(if y == 0 { None } else { Some((x, y - 1)) })
        .chain(if y == rows - 1 { None } else { Some((x, y + 1)) })
        .map(|(x, y)| x * 10 + y)  // get the &T here instead
}

What I don't get about the library either is why the functions have a signature like this:

pub fn iter_row(&self, row: usize) -> Iter<T>

I would think they might return Iter<&T> instead like in your example.

Iter<T> (which is probably short for Iter<'_, T>) can still implement Iterator<Item=&T>.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.