【问题标题】:Destructure a vector into variables and give away ownership?将向量解构为变量并放弃所有权?
【发布时间】:2017-09-25 05:40:15
【问题描述】:

我有一个结构

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

我想从一个向量创建一个Foo 的实例。

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!(),
}

我必须复制字符串吗?有没有更好的方法将向量解构为abcd 以及转移所有权?

其实我不介意x在解构后被完全销毁。所以我希望除了切片之外的向量也有模式匹配。目前看来我们只能解构切片。

【问题讨论】:

标签: rust


【解决方案1】:

我必须复制字符串吗?

如果您愿意放弃解构,则不会。我是 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,
        };
    }
}

这会将向量(以及成员)的所有权转移给迭代器,然后tuples 适配器将值分块到一个元组中。我们取其中的第一个并构造值。

如果您不想放弃整个向量的所有权,也可以使用drain

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

有没有更好的方法将向量解构为abcd 以及转移所有权?

不,除了迭代器之外,没有任何机制可以在不创建另一个 Vec(或具有相同限制的其他类型)的情况下获取 Vec 的一部分的所有权。

【讨论】:

    【解决方案2】:

    解构切片并不稳定,你不能移出切片,因为它只是一个借用——如果你移出,Vec 的析构函数会做什么?

    变异向量是这里的方法:

    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

    【讨论】:

    • 可以将Vec::drain() 与切片解构结合以提供移动+解构语义吗?
    • @user4815162342 你不能移出切片,因为数据结构本身无法跟踪它被移出的“洞”。由于drain 提供了一个迭代器,如果你想保留Vec,你可以将它与我的答案一起使用。
    • @Shepmaster 我正在回复部分答案,即您不能移出切片。由于drain() 专门用于将元素移出集合,我很好奇drain() 和切片解构组合的可能性,也许它们之间有一个中间类型。你的答案当然很好,但它不使用切片解构。
    • @user4815162342 明白了。我的观点是 slice destructuring 适用于 slices 并且您不能移出切片,因为它们始终代表借用的值,无论您采取哪种方式获得那里。听起来您需要一些其他解构技术(“vec 解构”?)。
    • @Shepmaster 是的,我想我希望 slice destructuring 实际上是用词不当,而且它不仅仅适用于切片。 :) 正确的名称意味着您只能在&[...] 中使用ref x,至少对于非Copy 类型,对吧?
    猜你喜欢
    • 1970-01-01
    • 2020-11-04
    • 2022-06-28
    • 1970-01-01
    • 1970-01-01
    • 2016-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多