Babbleopia
Babbleopia

Reputation: 11

What is the idiomatic way to transform vector of structs to another vector of structs

My function takes a Vec of structs as a parameter and places each of it's element into another vector as a new structure field:

fn new(cards: Vec<Card<'t>>) -> Self {
        CardsConnection {
            edges: cards.iter().map(|c| CardsConnectionEdge {
                cursor: c.id.clone(),
                node: *c
            }).collect::<Vec<CardsConnectionEdge>>()
        }
    }

I really want a move, so only new vector should own the Card instances. So since map got a reference, I want do dereference it to move the value, but I got the following error:

error[E0507]: cannot move out of `*c` which is behind a shared reference
  --> src/model.rs:74:23
   |
74 |                 node: *c
   |                       ^^ move occurs because `*c` has type `model::Card<'_>`, which does not implement the `Copy` trait

error: aborting due to previous error; 8 warnings emitted

While this non "functional-style" code works fine:

fn new(cards: Vec<Card<'t>>) -> Self {
        let mut edges = Vec::<CardsConnectionEdge>::with_capacity(cards.len());

        for c in cards {
            edges.push(CardsConnectionEdge {
                cursor: c.id.clone()
                node: c
            })
        }

        CardsConnection {
            edges
        }
    }

but looks a bit clumsy.

It there a way to do the same thing using iterators or some kind of map function? Or what is the idiomatic way of solving this kind of problems?

Upvotes: 1

Views: 834

Answers (1)

Ibraheem Ahmed
Ibraheem Ahmed

Reputation: 13578

You are looking for into_iter() The iter function iterates over the items by reference, while into_iter iterates over the items, moving them into a new scope.

So for c in cards {...} is essentially the same as cards.into_iter().for_each(|c| ... ). Both move the elements of cards into the ... scope.

fn new(cards: Vec<Card<'t>>) -> Self {
    CardsConnection {
        edges: cards
            .into_iter()
            .map(|c| CardsConnectionEdge {
                cursor: c.id.clone(),
                node: c,
            })
            .collect(),
    }
}

Reference: iter vs. into_iter

Upvotes: 3

Related Questions