# What's the ideomatic way to chain an iterator or reversed iterator?

I have a line of vertice, and want to try coupling it with another line of vertice.

``````Line 1: [1, 10, 20, 5]
Line 2: [1, 2, 3]

expected output:
Line 3: [3, 2, 1, 10, 20, 5] (or reversed order, doesn't matter)
``````

In the code I have to check 4 ways the lines can match. For example, lines with vertice `[1, 2]` and `[2, 3]` can appear like these:

``````[1, 2], [2, 3]
[1, 2], [3, 2] # need to reverse left or right
[2, 1], [2, 3] # need to reverse left or right
[2, 1], [3, 2]
``````

The output should be `[1, 2, 3]` or `[3, 2, 1]`.

Here's the code I could finally wrote. (In the real app, `Line` has other attributes, but for simplicity I omit them here.)

``````#[derive(Clone)]
struct Line {
vertice: Vec<i64>
}

impl Line {
fn ends(&self) -> [i64; 2] {
[self.vertice.clone(), self.vertice[self.vertice.len() - 1].clone()]
}
fn couple(&self, other: &Line) -> Option<Line> {
let new_vertice:Vec<i64> = {
let se = self.ends();
let oe = other.ends();
let mine = &self.vertice;
let their = &other.vertice;

if se == oe {
mine[1..].iter().rev().into_iter().chain(their.iter()).cloned().collect()
} else if se == oe {
their.iter().chain(mine[1..].iter()).cloned().collect()
} else if se == oe {
mine.iter().chain(their[1..].iter()).cloned().collect()
} else if se == oe {
mine[..mine.len() - 1].iter().chain(their.iter().rev()).cloned().collect()
} else {
return None;
}
};

Some(Line { vertice: new_vertice })
}
}

``````

I tried abstracting the code to reduce the repetitions of `chain`/`cloned`/`collect` calls, but it turned out even worse. A function can't accept `Iterator`/`Rev<X>`, only one of this kind, and I couldn't wrap them together. If instead I make a function accepting `Vec`, I need to call iter/cloned/collect to make a Vec before it.

``````
fn couple2(a: &Vec<i64>, b: &Vec<i64>) -> Vec<i64> {
a.iter().chain(b.iter()).cloned().collect()
}

...

if se == oe {
couple2(&mine[1..].iter().rev().cloned().collect(), their)
} else if se == oe {
couple2(their, &mine[1..].iter().cloned().collect())
} else if se == oe {
couple2(mine, &their[1..].iter().cloned().collect())
} else if se == oe {
couple2(&mine[..mine.len() - 1].iter().cloned().collect(), &their.iter().rev().cloned().collect())
...
``````

Did I miss some more ideomatic way to do this?

Maybe

``````fn couple2<'a, 'b>(
a: impl IntoIterator<Item = &'a i64>,
b: impl IntoIterator<Item = &'b i64>,
) -> Vec<i64> {
a.into_iter()
.copied()
.chain(b.into_iter().copied())
.collect()
}

....

if se == oe {
couple2(mine[1..].iter().rev(), their)
} else if se == oe {
couple2(their, &mine[1..])
} else if se == oe {
couple2(mine, &their[1..])
} else if se == oe {
couple2(&mine[..mine.len() - 1], their.iter().rev())
``````
1 Like

You could also integrate the logic of skipping one element of the second part into `couple2`:

``````fn couple2<'a, 'b>(
a: impl IntoIterator<Item = &'a i64>,
b: impl IntoIterator<Item = &'b i64>,
) -> Vec<i64> {
a.into_iter()
.copied()
.chain(b.into_iter().copied().skip(1))
.collect()
}

....

if se == oe {
couple2(mine.iter().rev(), their)
} else if se == oe {
couple2(their, mine)
} else if se == oe {
couple2(mine, their)
} else if se == oe {
couple2(mine, their.iter().rev())
``````

(untested)

1 Like

Another option:

``````fn couple2(a: impl Iterator<Item = i64>, b: impl Iterator<Item = i64>) -> Vec<i64> {
a.chain(b.skip(1)).collect()
}
....
let mine = self.vertice.iter().copied();
let their = other.vertice.iter().copied();

if se == oe {
couple2(mine.rev(), their)
} else if se == oe {
couple2(their, mine)
} else if se == oe {
couple2(mine, their)
} else if se == oe {
couple2(mine, their.rev())
} else {
return None;
}
``````
1 Like

Wow, it compiles!

I can't restore those old versions I had in the editor, but this looks a lot simpler and cleaner. What I missed was `skip(1)`.

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.