如何用迭代器将Vec<Row>转换为Vec<HashMap>(基于tiberius库)
将Vec转换为Vec<HashMap<String, String>>(基于tiberius模拟结构)
需求
使用tiberius查询SQL Server时,希望通过迭代器/Map模式将查询返回的Vec<Row>转换为Vec<HashMap<String, String>>,替代按列标签调用get方法的繁琐方式。单个Row转换后的HashMap期望格式:
{ "foo": "hello", "bar": "world" }
模拟数据结构及初始代码
#[derive(Debug)] struct Row { columns: Vec<Column>, data: TokenRow, result_index: usize, } #[derive(Debug)] struct TokenRow { data: Vec<Option<String>> } #[derive(Debug)] struct Column { name: String, column_type: String, } fn main() { let mut data: Vec<Row> = Vec::from([ Row { columns: Vec::from([ Column { name: String::from("foo"), column_type: String::from("string"), }, Column { name: String::from("bar"), column_type: String::from("string"), }, ]), data: TokenRow { data: Vec::from([ Some(String::from("hello")), Some(String::from("world")), ]), }, result_index: 0, } ]); dbg!(data); // 原尝试代码存在所有权冲突问题 let mut vals: Vec<(String, String)> = Vec::new(); for r in data { let res = r .columns .iter() .enumerate() .map(|(i, col)| { let col_name = col.name; // 尝试获取所有权会触发编译错误 let col_value = r.data.data[i]; // r已被移动,无法再次借用 (col_name, col_value) }) .collect(); vals.push(res) } dbg!(vals); }
解决方案
通过所有权转移和迭代器组合实现转换,彻底解决借用冲突:
use std::collections::HashMap; #[derive(Debug)] struct Row { columns: Vec<Column>, data: TokenRow, result_index: usize, } #[derive(Debug)] struct TokenRow { data: Vec<Option<String>> } #[derive(Debug)] struct Column { name: String, column_type: String, } fn main() { let data: Vec<Row> = vec![ Row { columns: vec![ Column { name: "foo".to_string(), column_type: "string".to_string(), }, Column { name: "bar".to_string(), column_type: "string".to_string(), }, ], data: TokenRow { data: vec![ Some("hello".to_string()), Some("world".to_string()), ], }, result_index: 0, } ]; // 转换为Vec<HashMap<String, String>> let result: Vec<HashMap<String, String>> = data .into_iter() .map(|row| { row.columns .into_iter() // 将列名与对应位置的可选值一一配对 .zip(row.data.data.into_iter()) // 过滤空值,同时提取Some中的字符串值 .filter_map(|(col, opt_val)| opt_val.map(|val| (col.name, val))) // 直接收集为HashMap .collect() }) // 收集所有HashMap为目标Vec .collect(); dbg!(result); }
关键说明
- 所有权处理:使用
into_iter()消费原Vec<Row>及内部的columns、data,规避借用生命周期冲突 - 元素配对:通过
zip方法将Column序列与Option<String>序列精准对应 - 空值过滤:
filter_map同时完成过滤None值和提取Some中有效字符串的操作 - 直接收集:利用迭代器的
collect()方法一步生成目标HashMap和Vec结构
内容的提问来源于stack exchange,提问作者Coldchain9
相关产品推荐
相关产品推荐

