gpt4 book ai didi

rust - 如何使用原始索引保留矢量元素?

转载 作者:行者123 更新时间:2023-12-03 11:35:58 24 4
gpt4 key购买 nike

如果我有一个 Vec我可以通过 v.iter().enumerate() 使用索引迭代元素,我可以通过 v.retain() 删除元素.有没有办法同时做到这两点?

在这种情况下,索引不能再用于访问元素——它将是循环开始之前元素的索引。

我可以自己实现,但要像 .retain() 一样高效我需要使用 unsafe ,我想避免。

这是我想要的结果:

let mut v: Vec<i32> = vec![1, 2, 3, 4, 5, 4, 7, 8];

v.iter()
.retain_with_index(|(index, item)| (index % 2 == 0) || item == 4);

assert(v == vec![1, 3, 4, 5, 4, 7]);

最佳答案

@Timmmm的和 @Hauleth的回答非常务实我想提供几个替代方案。

这是一个带有一些基准和测试的游乐场:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=cffc3c39c4b33d981a1a034f3a092e7b

这很难看,但如果你真的想要一个 v.retain_with_index()方法,你可以复制粘贴 retain具有新特征的方法:

trait IndexedRetain<T> {
fn retain_with_index<F>(&mut self, f: F)
where
F: FnMut(usize, &T) -> bool;
}

impl<T> IndexedRetain<T> for Vec<T> {
fn retain_with_index<F>(&mut self, mut f: F)
where
F: FnMut(usize, &T) -> bool, // the signature of the callback changes
{
let len = self.len();
let mut del = 0;
{
let v = &mut **self;

for i in 0..len {
// only implementation change here
if !f(i, &v[i]) {
del += 1;
} else if del > 0 {
v.swap(i - del, i);
}
}
}
if del > 0 {
self.truncate(len - del);
}
}
}

这样示例看起来像这样:

v.retain_with_index(|index, item| (index % 2 == 0) || item == 4);

或者……更好的是,您可以使用高阶函数:

fn with_index<T, F>(mut f: F) -> impl FnMut(&T) -> bool
where
F: FnMut(usize, &T) -> bool,
{
let mut i = 0;
move |item| (f(i, item), i += 1).0
}

这样这个例子现在看起来像这样:

v.retain(with_index(|index, item| (index % 2 == 0) || item == 4));

(我更喜欢后者)

关于rust - 如何使用原始索引保留矢量元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59602202/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com