Я пишу функцию слияния для векторов тегов с подсчетами, но получаю ошибки заимствования.«использование перемещенного значения» при сопоставлении при слиянии двух векторов
fn merge(mut l1: Vec<(String, u32)>, mut l2: Vec<(String, u32)>) -> Vec<(String, u32)> {
let mut d1 = l1.drain(..);
let mut d2 = l2.drain(..);
let mut result = Vec::new();
let mut v1 = d1.next();
let mut v2 = d2.next();
loop {
match (v1, v2) {
(None, None) => return result,
(None, Some(x)) => {
result.push(x.clone());
v2 = d2.next()
}
(Some(x), None) => {
result.push(x.clone());
v1 = d1.next()
}
(Some(p1), Some(p2)) => {
let (ref s1, t1) = p1;
let (ref s2, t2) = p2;
if s1 == s2 {
result.push((s1.clone(), t1 + t2));
v1 = d1.next();
v2 = d2.next();
} else if s1 < s2 {
result.push(p1.clone());
v1 = d1.next();
} else {
result.push(p2.clone());
v2 = d2.next();
}
}
}
}
}
выдает ошибку:
error: use of moved value: `v1` [E0382]
match (v1,v2) {
^~
help: run `rustc --explain E0382` to see a detailed explanation
note: `v1` was previously moved here because it has type `core::option::Option<(collections::string::String, u32)>`, which is non-copyable
и подобную ошибку для v2
. Обычно это показывает местоположение проблемы и предыдущий шаг, который вызывает проблему, но не здесь.
Я пробовал много перестановок, и со следующим изменением я получил его для компиляции, но я не доволен всем клонированием и воссозданием кортежей и воссозданием Option
.
match (v1, v2) {
(None, None) => return result,
(None, Some(x)) => {
result.push(x.clone());
v1 = None;
v2 = d2.next();
}
(Some(x), None) => {
result.push(x.clone());
v1 = d1.next();
v2 = None;
}
(Some(p1), Some(p2)) => {
let (ref s1, t1) = p1;
let (ref s2, t2) = p2;
if s1 == s2 {
result.push((s1.clone(), t1 + t2));
v1 = d1.next();
v2 = d2.next();
} else if s1 < s2 {
result.push(p1.clone());
v1 = d1.next();
v2 = Some((s2.clone(), t2));
} else {
result.push(p2.clone());
v1 = Some((s1.clone(), t1));
v2 = d2.next();
}
}
}
Добавление, что я бы на самом деле хотел написать, для справки, в случае, если кто-то ищет вызов для заема проверки:
fn merge(mut l1: Vec<(String, u32)>, mut l2: Vec<(String, u32)>) -> Vec<(String, u32)> {
let mut d1 = l1.drain(..);
let mut d2 = l2.drain(..);
let mut result = Vec::new();
let mut v1 = d1.next();
let mut v2 = d2.next();
loop {
match (v1, v2) {
(None, None) => return result,
(None, Some(p2)) => {
result.push(p2);
v1 = None;
v2 = d2.next()
}
(Some(p1), None) => {
result.push(p1);
v1 = d1.next();
v2 = None
}
(Some(p1 @ (s1, _)), o2 @ Some((s2, _))) if s1 < s2 => {
result.push(p1);
v1 = d1.next();
v2 = o2
}
(o1 @ Some((s1, _)), Some(p2 @ (s2, _))) if s1 > s2 => {
result.push(p2);
v1 = o1;
v2 = d2.next()
}
(Some((s1, t1)), Some((_, t2))) => {
result.push((s1, t1 + t2));
v1 = d1.next();
v2 = d2.next()
}
}
}
}
Обратите внимание, что матч на (v1, v2)
должен двигаться значения, чтобы каждый путь принудительно устанавливал v1
и v2
. Все еще не так чисто, как Хаскелл, но ближе.
вы имели в виду, чтобы вставить два примера вашего блока соответствия? Они выглядят одинаково для меня. –
второй присваивает как v1, так и v2 на каждой ветви, но имеет чрезмерные операции с клоном –