如何遍历Rust结构体字段并求和非rate后缀的字段?
在Rust中遍历结构体字段并求和(排除含"rate"的字段)
Rust本身没有内置的结构体字段遍历机制,不过可以通过以下几种方案实现需求:
方案一:借助Serde将结构体转为键值对遍历
因为你的结构体已经派生了serde::Deserialize,可以利用serde_json将结构体序列化为JSON对象,再遍历键值对过滤求和:
- 添加依赖到
Cargo.toml:
[dependencies] serde = { version = "1.0", features = ["derive"] } serde_json = "1.0"
- 实现代码:
use serde::Deserialize; use serde_json::Value; #[derive(Debug, Deserialize)] pub struct MyStruct { pub foo: f64, pub foo_rate: f64, pub bar: f64, pub bar_rate: f64, pub baz: f64, // 示例:无对应rate字段的字段 } fn main() { let my_struct = MyStruct { foo: 10.0, foo_rate: 0.5, bar: 20.0, bar_rate: 0.3, baz: 15.0, }; // 将结构体转为JSON对象 let json_val = serde_json::to_value(&my_struct).unwrap(); let obj = json_val.as_object().unwrap(); // 过滤并累加不含"rate"的字段值 let total: f64 = obj.iter() .filter(|(key, _)| !key.contains("rate")) .filter_map(|(_, val)| val.as_f64()) .sum(); println!("Total: {}", total); // 输出:45.0 }
方案二:使用反射库(如bevy_reflect)
通过反射机制直接获取结构体的字段信息,无需序列化:
- 添加依赖到
Cargo.toml:
[dependencies] bevy_reflect = { version = "0.12", features = ["derive"] }
- 实现代码:
use bevy_reflect::{Reflect, Struct}; #[derive(Debug, Reflect)] pub struct MyStruct { pub foo: f64, pub foo_rate: f64, pub bar: f64, pub bar_rate: f64, pub baz: f64, } fn main() { let my_struct = MyStruct { foo: 10.0, foo_rate: 0.5, bar: 20.0, bar_rate: 0.3, baz: 15.0, }; let mut total = 0.0; let struct_ref = my_struct.as_reflect(); let struct_data = struct_ref.downcast_ref::<Struct>().unwrap(); // 遍历所有字段 for (field_name, field_value) in struct_data.iter_fields() { if !field_name.contains("rate") { // 尝试将字段值转为f64 if let Some(val) = field_value.downcast_ref::<f64>() { total += val; } } } println!("Total: {}", total); // 输出:45.0 }
方案三:自定义过程宏(性能最优)
如果追求极致性能,不想依赖运行时库,可以写一个过程宏,在编译阶段生成求和代码。这种方式没有运行时开销,但需要编写宏代码,适合频繁调用的场景。核心逻辑是让宏遍历结构体所有字段,自动生成过滤"rate"字段并累加的代码,调用时直接执行生成的逻辑即可。
内容的提问来源于stack exchange,提问作者Antonin GAVREL
相关产品推荐
相关产品推荐

