如何将结构体集合拆分为结构体成员的集合?
将结构体集合转换为成员类型集合的Rust实现
要把Vec<Foo>拆分为分别对应每个结构体成员的引用集合(Vec<&String>, Vec<&i64>, Vec<&f64>),可以用以下几种方式实现:
1. 手动遍历收集(最直观)
直接遍历原集合,逐个提取成员引用并添加到对应向量中:
struct Foo { a: String, b: i64, c: f64, } fn main() { let foo = vec![ Foo { a: "hello".into(), b: 1, c: 1.0 }, Foo { a: "world".into(), b: 2, c: 2.0 }, ]; let mut a = Vec::new(); let mut b = Vec::new(); let mut c = Vec::new(); for f in &foo { a.push(&f.a); b.push(&f.b); c.push(&f.c); } // a: Vec<&String>, b: Vec<&i64>, c: Vec<&f64> }
2. 标准库迭代器fold方法(函数式写法)
用fold方法一次性完成三个向量的收集,无需手动初始化多个变量:
struct Foo { a: String, b: i64, c: f64, } fn main() { let foo = vec![ Foo { a: "hello".into(), b: 1, c: 1.0 }, Foo { a: "world".into(), b: 2, c: 2.0 }, ]; let (a, b, c) = foo.iter().fold( (Vec::new(), Vec::new(), Vec::new()), |(mut a_vec, mut b_vec, mut c_vec), f| { a_vec.push(&f.a); b_vec.push(&f.b); c_vec.push(&f.c); (a_vec, b_vec, c_vec) }, ); }
3. 第三方库itertools简化实现(最简洁)
如果可以引入第三方库itertools,可以用multiunzip方法一步完成转换,代码更简洁:
首先在Cargo.toml中添加依赖:
[dependencies] itertools = "0.12"
然后在代码中使用:
use itertools::Itertools; struct Foo { a: String, b: i64, c: f64, } fn main() { let foo = vec![ Foo { a: "hello".into(), b: 1, c: 1.0 }, Foo { a: "world".into(), b: 2, c: 2.0 }, ]; let (a, b, c): (Vec<&String>, Vec<&i64>, Vec<&f64>) = foo.iter() .map(|f| (&f.a, &f.b, &f.c)) .multiunzip(); }
额外说明:获取成员所有权而非引用
如果需要的是成员的所有权(比如Vec<String>而非Vec<&String>),可以改用into_iter消费原集合,并提取成员所有权:
// 消费原Vec<Foo>,得到所有权集合 let (a, b, c): (Vec<String>, Vec<i64>, Vec<f64>) = foo.into_iter() .map(|f| (f.a, f.b, f.c)) .multiunzip();
内容的提问来源于stack exchange,提问作者Siddharth Teli
相关产品推荐
相关产品推荐

