编写一个 Rust 函数来修改通用容器元素中的结构成员

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

是否可以编写一个函数来修改

struct
成员,以便可以将其与
Vec
HashMap::values()
一起使用?

这就是我到目前为止所想到的:

use std::collections::HashMap;

struct Foo {
    x: i32,
}

fn process_collection<T>(collection: &mut T)
where
    T: IntoIterator<Item = Foo>,
    for<'a> &'a mut T: IntoIterator<Item = &'a mut Foo>,
{
    for item in collection.into_iter() {
        item.x = 5;
    }
}

fn main() {
    let mut numbers = vec![Foo { x: 1 }, Foo { x: 2 }];
    // Set all .x members to 5.
    process_collection(&mut numbers); 
    
    for item in &numbers {
        println!("item after: {}", item.x);
    }
    
    let mut data: HashMap<String, Foo> = HashMap::new();
    data.insert("One".to_string(), Foo {x: 1} );
    data.insert("Two".to_string(), Foo {x: 2});
    
    // This does not compile.
    process_collection(&mut data.values()); 
}
rust iterator
2个回答
0
投票

values
迭代对值的 immutable 引用,如果您需要独占引用才能改变值,则必须使用
values_mut

此外,在

&mut T
中写出可变引用是极其有限的,并且根本不允许
ValuesMut
(对值的可变引用的迭代器)(它也不实现
IntoIterator
,而只是采用
T: IntoIterator<&mut Foo>
:

fn process_collection<'a, T>(collection: T)
where
    T: IntoIterator<Item = &'a mut Foo>,
{
    for item in collection.into_iter() {
        item.x = 5;
    }
}

fn main() {
    let mut numbers = vec![Foo { x: 1 }, Foo { x: 2 }];
    // Set all .x members to 5.
    process_collection(&mut numbers); 
    
    for item in &numbers {
        println!("item after: {}", item.x);
    }
    
    let mut data: HashMap<String, Foo> = HashMap::new();
    data.insert("One".to_string(), Foo {x: 1} );
    data.insert("Two".to_string(), Foo {x: 2});
    
    process_collection(data.values_mut()); 
    for item in data.values() {
        println!("item after: {}", item.x);
    }
}

0
投票

要修改适当的元素,您只需要一个具有可变访问权限的迭代器:

fn process_collection<'a, T>(collection: T)
where
    T: IntoIterator<Item = &'a mut Foo>,
{
    for item in collection {
        item.x = 5;
    }
}

您可以使用

Vec<Foo>
进行呼叫,如下所示:

process_collection(&mut numbers);

或者使用

HashMap<_, Foo>
中的值,如下所示:

process_collection(data.values_mut()); 

注意更改:

  • 您不需要同时使用
    T: IntoIterator
    &mut T: IntoIterator
    。尽管集合通常具有这两种实现,但这不是必需的,也不适用于
    HashMap
    的值。
  • 这使用
    values_mut()
    而不是仅
    values()
    ,因为后者仅提供不可变引用。
  • collection
    作为自有值传递,而不是作为可变引用传递,因为它更惯用。
© www.soinside.com 2019 - 2024. All rights reserved.