You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用迭代器将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);
}

关键说明

  1. 所有权处理:使用into_iter()消费原Vec<Row>及内部的columns、data,规避借用生命周期冲突
  2. 元素配对:通过zip方法将Column序列与Option<String>序列精准对应
  3. 空值过滤:filter_map同时完成过滤None值和提取Some中有效字符串的操作
  4. 直接收集:利用迭代器的collect()方法一步生成目标HashMap和Vec结构

内容的提问来源于stack exchange,提问作者Coldchain9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 16:41:19