如何在不复制的情况下将字符串值从数组移动到元组?

时间:2016-07-10 10:12:06

标签: arrays rust tuples

我有一个固定大小的String s:[String; 2]数组。我想把它变成(String, String)。我可以不复制值吗?

我正在处理的一段代码如下:

let (basis, names_0, names_1) = if let Some(names) = self.arg_name {
    (ComparisonBasis::Name, names[0], names[1])
} else {
    (ComparisonBasis::File, self.arg_file[0], self.arg_file[1])
};

类型:

self.arg_name: Option<[String; 2]>
self.arg_file: Vec<String>

现在我收到错误

cannot move out of type `[std::string::String; 2]`, a non-copy fixed-size array [E0508]

cannot move out of indexed content [E0507]

表示if

的两个部分

2 个答案:

答案 0 :(得分:4)

您已经省略了相当多的背景,因此我在几个方面进行了猜测。我也会更接近你问的问题,而不是你的片段隐含的模糊。

struct NeverSpecified {
    arg_names: Option<[String; 2]>,
    arg_file: Vec<String>,
}

impl NeverSpecified {
    fn some_method_i_guess(mut self) -> (String, String) {
        if let Some(mut names) = self.arg_names {
            use std::mem::replace;
            let name_0 = replace(&mut names[0], String::new());
            let name_1 = replace(&mut names[1], String::new());
            (name_0, name_1)
        } else {
            let mut names = self.arg_file.drain(0..2);
            let name_0 = names.next().expect("expected 2 names, got 0");
            let name_1 = names.next().expect("expected 2 names, got 1");
            (name_0, name_1)
        }
    }
}

我使用std::mem::replace来切换数组的内容,同时使其保持有效状态。这是必要的,因为Rust不会让你有一个部分有效的&#34;阵列。此路径中没有涉及副本或分配。

在另一条路径中,我们必须手动将元素从向量中拉出来。同样,您不能仅通过索引将值移出容器(这实际上是整体索引的限制)。相反,我使用Vec::drain基本上切掉了向量中的前两个元素,然后从生成的迭代器中提取它们。要明确:此路径不涉及任何副本或分配,

顺便说一句,那些expect方法不应该被触发(因为drain确实需要检查),但是更好的偏执而不是抱歉;如果你想用unwrap()来代替它们,那应该没问题。

答案 1 :(得分:1)

如果您愿意使用夜间功能,可以使用切片模式一次绑定到数组的所有值:

#![feature(slice_patterns)]

struct NeverSpecified {
    arg_names: Option<[String; 2]>,
    arg_file: Vec<String>,
}

impl NeverSpecified {
    fn some_method_i_guess(mut self) -> (String, String) {
        if let Some([name_0, name_1]) = self.arg_names.take() {
            (name_0, name_1)
        } else {
            let mut names = self.arg_file.drain(0..2);
            let name_0 = names.next().expect("expected 2 names, got 0");
            let name_1 = names.next().expect("expected 2 names, got 1");
            (name_0, name_1)
        }
    }
}