1

I was diving into Rust head-first again now, making a function to remove every other element:

fn remove_every_other(arr: &[u8]) -> Vec<u8> {
    arr.iter().step_by(2).collect::<Vec<_>>()
}

But then I was hit with this error:

  |
1 | fn remove_every_other(arr: &[u8]) -> Vec<u8> {
  |                                      ------- expected `Vec<u8>` because of return type
2 |     arr.iter().step_by(2).collect::<Vec<_>>()
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `&u8`
  |
  = note: expected struct `Vec<u8>`
             found struct `Vec<&u8>`

That's an easy fix for me, just map and dereference, right?

arr.iter().step_by(2).map(|x| *x).collect::<Vec<_>>()

However, I don't think this is the right way... it feels dirty.

I also tried using into_iter because in the three forms of iteration, it was listed to return T and not &T, but using it gives me the same error(?).

Is there a "cleaner" or better way to do this? I was unable to find the right terms to search for this, so if you've got the question I need to see, I'll gladly close as a duplicate :)

Playground

kelsny
  • 23,009
  • 3
  • 19
  • 48
  • [Similar question here.](https://stackoverflow.com/questions/53115999/what-is-the-idiomatic-way-of-converting-a-vec-of-references-to-a-vec-of-values) – kelsny Oct 05 '22 at 23:02
  • Honestly, might need to update the part about the three forms of iteration... `into_iter` returns `T`, `&T`, and `&mut T` depending on the context... But they were specifically talking about collections so I suppose that's excusable. – kelsny Oct 07 '22 at 15:17

1 Answers1

3

Well, I just read the entire page of documentation to find these two methods:

copied:

arr.iter().step_by(2).copied().collect()

cloned:

arr.iter().step_by(2).cloned().collect()

However, this won't work for all T, only ones that implement Copy or Clone.

kelsny
  • 23,009
  • 3
  • 19
  • 48
  • If `T` is neither `Copy` nor `Clone`, your function must take the input by value (e.g. `fn remove_every_other(arr: Vec) -> Vec`), and then you can use `arr.into_iter`. – Jmb Oct 06 '22 at 06:58
  • Just to add to @Jmb's comment, you could accept a parameter of type `impl IntoIterator` in order that anything implementing the trait will be accepted rather than being explicit that you require a `Vec` or whatever. You may even prefer to accept an `impl Iterator` if you want callers to be able to provide some arbitrary iterator that produces such values rather than a collection of them. – eggyal Oct 06 '22 at 10:46