我正在寻找一种方法,它可以生成一个Vec并返回一个元素,而不需要像removeswap_remove那样恢复Vec的不变量:

fn take<T>(vec: Vec<T>, index: usize) -> Option<T>

然而,我找不到这样的方法.我错过什么了吗?这真的不安全还是不可能?

这是一个与Built in *safe* way to move out of Vec<T>?不同的问题

推荐答案

你可以这样写你的函数:

fn take<T>(mut vec: Vec<T>, index: usize) -> Option<T> {
    if vec.get(index).is_none() {
        None
    } else {
        Some(vec.swap_remove(index))
    }
}

这里的代码see(getswap_remove)保证为O(1).

However,有点隐藏,vec在函数末尾被删除,这个删除操作可能不是O(1),而是O(n)(其中n是vec.len()).如果T实现Drop,那么对于仍然在向量内的每个元素调用drop(),这意味着丢弃向量保证为O(n).如果T没有实现Drop,那么Vec只需要释放内存.dealloc操作的时间复杂度取决于分配器,并且没有指定,因此我们不能假设它是O(1).


提到另一个使用迭代器的解决方案:

fn take<T>(vec: Vec<T>, index: usize) -> Option<T> {
    vec.into_iter().nth(index)
}

我正要写这封信:

虽然Iterator::nth()通常是linear time运算,但向量上的迭代器会覆盖此方法,使其成为O(1)运算.

但后来我注意到,这只适用于迭代切片的迭代器.上面代码中使用的std::vec::IntoIter迭代器不会覆盖nth().已经try 了here次,但似乎没有那么容易.

所以,到目前为止,上面的迭代器解决方案是一个O(n)操作!更不用说如上所述,放下向量所需的时间了.

Rust相关问答推荐

if let声明中临时对象的生存期

使用InlineTables序列化toml ArrayOfTables

有没有方法处理rust中嵌套的ok_or()?

即使参数和结果具有相同类型,fn的TypId也会不同

当为a Self:IntoIterator设置trait bind `时,获取`a T `不是迭代器"&'"<'>&'

为什么要在WASM库中查看Rust函数需要`#[no_mangle]`?

铁 rust ,我的模块介绍突然遇到了一个问题

零拷贝按步骤引用一段字节

更合理的方法来设计样条线函数器?

为什么RefCell没有与常规引用相同的作用域?

为什么不';t(&;mut-iter).take(n)取得iter的所有权?

为相同特征的特征对象使用 move 方法实现特征

在 Rust 中,在第一个空格上分割字符串一次

为什么是&mut发送?线程如何在安全的 Rust 中捕获 &mut?

如何在 Emacs Elisp 中获得类似格式化的 LSP?

改变不实现克隆的 dioxus UseState struct

将一片字节复制到一个大小不匹配的数组中

Rust 中的let是做什么的?

将数据序列化为 struct 模型,其中两个字段的数据是根据 struct 中的其他字段计算的

为什么在使用 self 时会消耗 struct 而在解构时不会?