有没有一种方法可以优雅地解决“在可变引用后面移动”而不实现“复制”特征?

问题描述 投票:0回答:1

我正在尝试在 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
的原因相同。

我的问题是:有没有办法在保留泛型类型的同时解决这个问题? 这几乎是自相矛盾的,因为理论上这是一项非常简单的任务 - “只需将元素的所有权从一个向量移动到另一个向量” - 但由于所有权规则,这并不那么简单。

rust mergesort borrow-checker
1个回答
0
投票

您可以迭代

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
)为空,但合并后仍保留其原始容量。

© www.soinside.com 2019 - 2024. All rights reserved.