Vector 如何将向量中的一个元素替换为基于原始元素的另一个元素 请考虑下面的程序(这是一个最小化的例子,所以不要挂断事实,我在这里做的事情可以用 HashMap 更好地实现): #[派生(PartialEq)] 枚举MyVariant{ 没有一个 一些价值, 其他价值观, 骨料(Vec) } impl-MyVariant{ 带有(self,其他:self)->self的pub fn{ 如果self==self::无{ 其他 }如果其他==Self::无,则为else{ 自己 }否则{ Self::聚合(vec![Self,other]) } } } fn添加变量(vec:&mut vec,id:u32,变量:MyVariant){ 如果让某些(项)=vec.iter_mut().find(|项|项.0==id){ *item=(id,item.1.with(variant)); }否则{ 向量推送((id,变量)); } } fn main(){ 让mut-vec:vec=vec::new(); 添加变量(&mut-vec,1,MyVariant::SomeValue); 添加变量(&mut-vec,2,MyVariant::None); 添加变量(&mut-vec,1,MyVariant::SomeOtherValue); }
这将在Vector 如何将向量中的一个元素替换为基于原始元素的另一个元素 请考虑下面的程序(这是一个最小化的例子,所以不要挂断事实,我在这里做的事情可以用 HashMap 更好地实现): #[派生(PartialEq)] 枚举MyVariant{ 没有一个 一些价值, 其他价值观, 骨料(Vec) } impl-MyVariant{ 带有(self,其他:self)->self的pub fn{ 如果self==self::无{ 其他 }如果其他==Self::无,则为else{ 自己 }否则{ Self::聚合(vec![Self,other]) } } } fn添加变量(vec:&mut vec,id:u32,变量:MyVariant){ 如果让某些(项)=vec.iter_mut().find(|项|项.0==id){ *item=(id,item.1.with(variant)); }否则{ 向量推送((id,变量)); } } fn main(){ 让mut-vec:vec=vec::new(); 添加变量(&mut-vec,1,MyVariant::SomeValue); 添加变量(&mut-vec,2,MyVariant::None); 添加变量(&mut-vec,1,MyVariant::SomeOtherValue); },vector,rust,Vector,Rust,这将在*item=(id,item.1.with(variant))处失败,因为item是一个共享的可变引用,因此item.1不能移动到with()方法中。我试着使用一个指向向量的索引来获取一个引用,但这并不能解决根本的问题 基本上,我想要的是一个方法,它将临时将一个值移出可变向量,并用一个新的派生值替换它。可能是这样的: impl-Vec{ ///将“index”处的项替换为“replacer”生成的新项。 ///'replacer'将旧项作为参数接收。 fn替换_为(&mut self,索引
*item=(id,item.1.with(variant))
处失败,因为item
是一个共享的可变引用,因此item.1
不能移动到with()
方法中。我试着使用一个指向向量的索引来获取一个引用,但这并不能解决根本的问题
基本上,我想要的是一个方法,它将临时将一个值移出可变向量,并用一个新的派生值替换它。可能是这样的:
impl-Vec{
///将“index”处的项替换为“replacer”生成的新项。
///'replacer'将旧项作为参数接收。
fn替换_为(&mut self,索引:usize,替换:fn(T)->T);
}
但我找不到像上面这样的方法,也找不到任何能达到同样目的的技术
我想我可能是从错误的角度看问题,有什么想法吗?谢谢 此代码应该可以工作。它与您的不同之处在于,它构造了一个临时占位符,然后使用
std::mem::swap
将其交换到Vec
中,以便通过值传递实际值
#[derive(PartialEq)]
enum MyVariant {
None,
SomeValue,
SomeOtherValue,
Aggregate(Vec<MyVariant>)
}
impl MyVariant {
pub fn with(self, other: Self) -> Self {
if self == Self::None {
other
} else if other == Self::None {
self
} else {
Self::Aggregate(vec![self, other])
}
}
}
fn add_variant(vec: &mut Vec<(u32, MyVariant)>, id: u32, variant: MyVariant) {
if let Some(item) = vec.iter_mut().find(|item| item.0 == id) {
let mut temp = (0, MyVariant::None); // create placeholder value
std::mem::swap(item, &mut temp); // swap the placeholder in
*item = (id, temp.1.with(variant)); // overwrite with real value
} else {
vec.push((id, variant));
}
}
fn main() {
let mut vec: Vec<(u32, MyVariant)> = Vec::new();
add_variant(&mut vec, 1, MyVariant::SomeValue);
add_variant(&mut vec, 2, MyVariant::None);
add_variant(&mut vec, 1, MyVariant::SomeOtherValue);
}
#[派生(PartialEq)]
枚举MyVariant{
没有一个
一些价值,
其他价值观,
骨料(Vec)
}
impl-MyVariant{
带有(self,其他:self)->self的pub fn{
如果self==self::无{
其他
}如果其他==Self::无,则为else{
自己
}否则{
Self::聚合(vec![Self,other])
}
}
}
fn添加变量(vec:&mut vec,id:u32,变量:MyVariant){
如果让某些(项)=vec.iter_mut().find(|项|项.0==id){
让mut temp=(0,MyVariant::None);//创建占位符值
std::mem::swap(item,&mut temp);//在中交换占位符
*item=(id,temp.1.with(variant));//用实际值覆盖
}否则{
向量推送((id,变量));
}
}
fn main(){
让mut-vec:vec=vec::new();
添加变量(&mut-vec,1,MyVariant::SomeValue);
添加变量(&mut-vec,2,MyVariant::None);
添加变量(&mut-vec,1,MyVariant::SomeOtherValue);
}
此代码应该有效。它与您的不同之处在于,它构造了一个临时占位符,然后使用std::mem::swap
将其交换到Vec
中,以便通过值传递实际值
#[derive(PartialEq)]
enum MyVariant {
None,
SomeValue,
SomeOtherValue,
Aggregate(Vec<MyVariant>)
}
impl MyVariant {
pub fn with(self, other: Self) -> Self {
if self == Self::None {
other
} else if other == Self::None {
self
} else {
Self::Aggregate(vec![self, other])
}
}
}
fn add_variant(vec: &mut Vec<(u32, MyVariant)>, id: u32, variant: MyVariant) {
if let Some(item) = vec.iter_mut().find(|item| item.0 == id) {
let mut temp = (0, MyVariant::None); // create placeholder value
std::mem::swap(item, &mut temp); // swap the placeholder in
*item = (id, temp.1.with(variant)); // overwrite with real value
} else {
vec.push((id, variant));
}
}
fn main() {
let mut vec: Vec<(u32, MyVariant)> = Vec::new();
add_variant(&mut vec, 1, MyVariant::SomeValue);
add_variant(&mut vec, 2, MyVariant::None);
add_variant(&mut vec, 1, MyVariant::SomeOtherValue);
}
#[派生(PartialEq)]
枚举MyVariant{
没有一个
一些价值,
其他价值观,
骨料(Vec)
}
impl-MyVariant{
带有(self,其他:self)->self的pub fn{
如果self==self::无{
其他
}如果其他==Self::无,则为else{
自己
}否则{
Self::聚合(vec![Self,other])
}
}
}
fn添加变量(vec:&mut vec,id:u32,变量:MyVariant){
如果让某些(项)=vec.iter_mut().find(|项|项.0==id){
让mut temp=(0,MyVariant::None);//创建占位符值
std::mem::swap(item,&mut temp);//在中交换占位符
*item=(id,temp.1.with(variant));//用实际值覆盖
}否则{
向量推送((id,变量));
}
}
fn main(){
让mut-vec:vec=vec::new();
添加变量(&mut-vec,1,MyVariant::SomeValue);
添加变量(&mut-vec,2,MyVariant::None);
添加变量(&mut-vec,1,MyVariant::SomeOtherValue);
}
鉴于您无法复制或克隆变体,并且with
拥有所有权,您需要输入一个虚拟值,以避免出现单元化内存。您可以使用std::mem::replace
:
fn add_variant(vec: &mut Vec<(u32, MyVariant)>, id: u32, variant: MyVariant) {
if let Some(item) = vec.iter_mut().find(|item| item.0 == id) {
let old_item = std::mem::replace(&mut item.1, MyVariant::None);
item.1 = old_item.with(variant);
} else {
vec.push((id, variant));
}
}
fn添加变量(vec:&mut-vec,id:u32,变量:MyVariant){
如果让某些(项)=vec.iter_mut().find(|项|项.0==id){
让old_item=std::mem::replace(&mut item.1,MyVariant::None);
项目1=旧项目,带有(变体);
}否则{
向量推送((id,变量));
}
}
鉴于您无法复制或克隆变体,并且with
拥有所有权,您需要输入一个虚拟值,以避免出现单元化内存。您可以使用std::mem::replace
:
fn add_variant(vec: &mut Vec<(u32, MyVariant)>, id: u32, variant: MyVariant) {
if let Some(item) = vec.iter_mut().find(|item| item.0 == id) {
let old_item = std::mem::replace(&mut item.1, MyVariant::None);
item.1 = old_item.with(variant);
} else {
vec.push((id, variant));
}
}
fn添加变量(vec:&mut-vec,id:u32,变量:MyVariant){
如果让某些(项)=vec.iter_mut().find(|项|项.0==id){
让old_item=std::mem::replace(&mut item.1,MyVariant::None);
项目1=旧项目,带有(变体);
}否则{
向量推送((id,变量));
}
}
中有很多不错的选项,但您可以在结构实现本身中进行替换:
impl MyVariant {
pub fn with_inplace(&mut self, other: Self) {
if self == &Self::None {
*self = other
} else {
if other != Self::None {
let tmp = std::mem::replace(self, Self::None);
*self = Self::Aggregate(vec![tmp, other]);
}
}
}
}
然后在迭代中调用它:
if let Some(item) = vec.iter_mut().find(|item| item.0 == id) {
item.1.with_inplace(variant);
} else {
vec.push((id, variant));
}
中有很好的选项,但您可以在结构实现本身中进行替换:
impl MyVariant {
pub fn with_inplace(&mut self, other: Self) {
if self == &Self::None {
*self = other
} else {
if other != Self::None {
let tmp = std::mem::replace(self, Self::None);
*self = Self::Aggregate(vec![tmp, other]);
}
}
}
}
然后在迭代中调用它:
if let Some(item) = vec.iter_mut().find(|item| item.0 == id) {
item.1.with_inplace(variant);
} else {
vec.push((id, variant));
}
或者呢?这个变量没有默认值(虽然我想我可以添加它),但实际上我可以使用两个std::mem::swap()
调用来解决它。我只是希望有一个更符合人体工程学的API…更新:正如彼得·霍尔的回答所示,我已经决定了