我正在尝试在 Rust 中实现合并排序的合并功能。问题是我试图对通用类型
T
执行此操作,该类型仅受 std::cmp::PartialOrd
限制。
这是代码:
fn my_merge<T: std::cmp::PartialOrd>(a: &mut Vec<T>, mut b: &mut Vec<T>) -> Vec<T> {
let mut res: Vec<T> = Vec::new();
let mut a_iter = a.into_iter(); // !!!
let mut b_iter = b.into_iter(); // !!!
while let (Some(a_item), Some(b_iter)) = (a_iter.next(), b_iter.next()) {
if a_item <= b_item {
res.push(*a_item); // !!!
} else {
res.push(*b_item); // !!!
}
}
// ... Omitted code ...
res
}
在查看文档时,我发现了
into_iter()
方法,使用该方法 next()
方法应该产生 T
而不是 &T
。但只有当迭代器不是在引用上构造时,它才会这样做(因为我将切片传递到函数中)。
(快速提醒:这是因为借用的工作原理。请参阅此 StackOverflow 问题)
这与您无法在带注释的行上取消引用变量
a_item
和 b_item
的原因相同。
我的问题是:有没有办法在保留泛型类型的同时解决这个问题? 这几乎是自相矛盾的,因为理论上这是一项非常简单的任务 - “只需将元素的所有权从一个向量移动到另一个向量” - 但由于所有权规则,这并不那么简单。
您可以迭代
Vec
,同时声明元素的所有权,而无需使用 Vec
:消耗原始
.drain(..)
本身
fn my_merge<T: std::cmp::PartialOrd>(a: &mut Vec<T>, b: &mut Vec<T>) -> Vec<T> {
let mut res: Vec<T> = Vec::new();
let mut a_iter = a.drain(..);
let mut b_iter = b.drain(..);
while let (Some(a_item), Some(b_item)) = (a_iter.next(), b_iter.next()) {
if a_item <= b_item {
res.push(a_item);
} else {
res.push(b_item);
}
}
res
}
这当然会使输入(
a
和b
)为空,但合并后仍保留其原始容量。