Vector 在没有内存分配的情况下,我如何变异并有选择地从vec中删除元素?
我有一个Player结构,它包含一个效果实例的vec。我想迭代这个vec,减少每个效果的剩余时间,然后删除剩余时间为零的任何效果。到现在为止,一直都还不错。但是,对于任何移除的效果,我还希望在销毁效果实例之前将其传递给播放器的undo_effect()方法 这是游戏循环的一部分,因此如果可能的话,我希望在没有任何额外内存分配的情况下执行此操作 我尝试过使用一个简单的for循环以及迭代器、drain、retain和filter,但我一直遇到self(玩家)会被多次可变借用的问题,因为修改self.effects需要可变借用,就像undo_effect()方法一样。《夜间》中的drain_filter()在这里看起来很有用,但它是在2017年首次提出的,所以我不会屏住呼吸 编译的一种方法(见下文)是使用两个向量,并在每一帧上交替使用。元素从vec 1弹出(),并根据需要推送()到vec 2或传递到undo_effect()。在下一个游戏循环迭代中,方向是相反的。由于每个vec都不会收缩,因此只有当它们比以前更大时,才会进行分配。 我开始将其抽象为自己的结构,但想检查是否有更好(或更简单)的方法 这个不能编译。调用self.undo_effect()会将self作为可变项借用两次Vector 在没有内存分配的情况下,我如何变异并有选择地从vec中删除元素?,vector,rust,borrowing,Vector,Rust,Borrowing,我有一个Player结构,它包含一个效果实例的vec。我想迭代这个vec,减少每个效果的剩余时间,然后删除剩余时间为零的任何效果。到现在为止,一直都还不错。但是,对于任何移除的效果,我还希望在销毁效果实例之前将其传递给播放器的undo_effect()方法 这是游戏循环的一部分,因此如果可能的话,我希望在没有任何额外内存分配的情况下执行此操作 我尝试过使用一个简单的for循环以及迭代器、drain、retain和filter,但我一直遇到self(玩家)会被多次可变借用的问题,因为修改self.
struct播放器{
效果:Vec
}
impl播放器{
fn更新(&mut self,增量时间:f32){
用于在多个自我影响中的效果(&M){
影响。剩余-=增量时间;
如果effect.remaining如果我理解正确,您有两个问题:
如何将Vec
拆分为两个Vec
s(一个满足预测,另一个不满足预测)
有没有可能不增加内存开销
有多种方法可以将Vec拆分为两个(或多个)
- 您可以使用它,它将为您提供两个不同的迭代器,可以进一步使用它们
- 有一个不稳定的函数,其作用与此相同,但它位于
Vec
本身
- 使用(或
splitn_mut
)将Vec/切片拆分为n
(在您的情况下为2个)迭代器
根据您想要做的事情,所有解决方案都适用且易于使用
是否可能没有内存开销?不使用上述解决方案,因为您需要创建第二个Vec
,该Vec可以保存筛选的项目。但有一个解决方案,即您可以“排序”Vec,其中前半部分将包含满足谓词的所有项目(例如未过期)第二部分将使谓词失败(过期)。您只需要计算满足谓词的项的数量
然后,您可以使用(或split_at_mut
)将Vec/切片拆分为两个不同的切片。之后,您可以将Vec调整为良好项目的长度,其他项目将被删除。如果我理解正确,您有两个问题:
如何将Vec
拆分为两个Vec
s(一个满足预测,另一个不满足预测)
有没有可能不增加内存开销
有多种方法可以将Vec拆分为两个(或多个)
- 您可以使用它,它将为您提供两个不同的迭代器,可以进一步使用它们
- 有一个不稳定的函数,其作用与此相同,但它位于
Vec
本身
- 使用(或
splitn_mut
)将Vec/切片拆分为n
(在您的情况下为2个)迭代器
根据您想要做的事情,所有解决方案都适用且易于使用
是否可能没有内存开销?不使用上述解决方案,因为您需要创建第二个Vec
,该Vec可以保存筛选的项目。但有一个解决方案,即您可以“排序”Vec,其中前半部分将包含满足谓词的所有项目(例如未过期)第二部分将使谓词失败(过期)。您只需要计算满足谓词的项的数量
然后,您可以使用(或split_at_mut
)将Vec/切片分割为两个不同的切片。之后,您可以将Vec调整为良好项目的长度,其他项目将被删除。主要问题是您借用了一个字段(效果)在借用此字段时,尝试调用undo_effect
。如您所述,这不起作用
您已经意识到可以处理两个向量,但实际上只能处理一个(永久)向量:
struct播放器{
效果:Vec
}
impl播放器{
fn更新(&mut self,增量时间:f32){
用于在多个自我影响中的效果(&M){
影响。剩余-=增量时间;
如果effect.remaining,主要问题是您正在借用Player
的一个字段(effects
),并试图在借用该字段时调用undo\u effect
。如您所述,这不起作用
您已经意识到可以处理两个向量,但实际上只能处理一个(永久)向量:
struct播放器{
效果:Vec
}
impl播放器{
fn更新(&mut self,增量时间:f32){
用于在多个自我影响中的效果(&M){
影响。剩余-=增量时间;
如果有效剩余最好的答案是
[O] 对索引向量排序,在数据向量中创建两个迭代器,一个用于读取,一个用于写入。将写入迭代器初始化为要删除的第一个元素,将读取迭代器初始化为要删除的第一个元素之外的元素。然后在循环的每个步骤中,将迭代器递增到下一个值(写入),而不递增到下一个值
struct Player {
effects: Vec<Effect>
}
impl Player {
fn update(&mut self, delta_time: f32) {
for effect in &mut self.effects {
effect.remaining -= delta_time;
if effect.remaining <= 0.0 {
effect.active = false;
}
}
// Temporarily remove effects from Player.
let mut effects = std::mem::replace(&mut self.effects, vec!());
// Call Player::undo_effects (no outstanding borrows).
// `drain_filter` could also be used, for better efficiency.
for effect in effects.iter_mut().filter(|e| !e.active) {
self.undo_effect(effect);
}
// Restore effects
self.effects = effects;
self.effects.retain(|e| e.active);
}
}