Destructure a vector into variables and give away ownership?

和自甴很熟 提交于 2020-01-04 06:05:09

问题


I have a struct

struct Foo {
    foo1: String,
    foo2: String,
    foo3: String,
    foo4: String,
    // ...
}

I would like to create an instance of Foo from a vector.

let x = vec!["a".to_string(), "b".to_string(), "c".to_string(), "d".to_string()];
match x.as_slice() {
    &[ref a, ref b, ref c, ref d] => {
        let foo = Foo {
            foo1: a.to_string(),
            foo2: b.to_string(),
            foo3: c.to_string(),
            foo4: d.to_string(),
        };

    },
    _ => unreachable!(),
}

Do I have to copy the strings? Is there any better way to destructure the vector into a, b, c, d as well as transferring the ownership?

Actually, I don't mind x is completely destroyed after the destructuring. So I hope there is a pattern match for vectors apart from slices as well. For now it seems we can only destructure slices.


回答1:


Do I have to copy the strings?

Not if you are willing to give up destructuring. I'm a big fan of itertools:

use itertools::Itertools; // 0.8.2

fn main() {
    let x = vec![
        "a".to_string(),
        "b".to_string(),
        "c".to_string(),
        "d".to_string(),
    ];

    if let Some((foo1, foo2, foo3, foo4)) = x.into_iter().tuples().next() {
        let foo = Foo {
            foo1,
            foo2,
            foo3,
            foo4,
        };
    }
}

This transfers ownership of the vector (and thus the members) to an iterator, then the tuples adapter chunks up the values into a tuple. We take the first one of those and construct the value.

You could also use drain if you didn't want to give up ownership of the entire vector:

if let Some((foo1, foo2, foo3, foo4)) = x.drain(..4).tuples().next() {

Is there any better way to destructure the vector into a, b, c, d as well as transferring the ownership?

No, there is no mechanism to take ownership of a part of a Vec without creating another Vec (or another type that has the same limits) except for an iterator.




回答2:


Destructuring slices isn't stable, and you can't move out of a slice because it's just a borrow — if you moved out, what would the Vec's destructor do?

Mutating the vector is the way to go here:

let mut x = vec!["a".to_string(), "b".to_string(), "c".to_string(), "d".to_string()];
let foo = Foo {
    foo4: x.pop().unwrap(),
    foo3: x.pop().unwrap(),
    foo2: x.pop().unwrap(),
    foo1: x.pop().unwrap(),
};

println!("{:?}", foo);

playground



来源:https://stackoverflow.com/questions/43657570/destructure-a-vector-into-variables-and-give-away-ownership

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!