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

如何将CsvHelper读取的List转换为List<Dictionary<string,object>>

问题描述

已有含重复X (mm)、Y (mm)列的CSV文件,通过CsvHelper成功读取为List<SicaGraphData>集合。现需将该集合转换为List<Dictionary<string, object>>格式,使数据呈现类似Y (mm): -61.232543的键值对形式,以便后续转为DataTable存入MongoDB。

CSV示例

23.75,-71.14026637566099,23.26,-68.14,X (mm),Y (mm),X (mm),Y (mm),X (mm),Y (mm)
75.0,0.0,72.0,0.0,-70.8744,-11.0272,-62.1812,-22.0121,1.1013,5.3621
...

当前读取代码

class CsvHelperTester
{
    static void Main(string[] args)
    {
        var config = new CsvConfiguration(CultureInfo.InvariantCulture)
        {
            HasHeaderRecord = false,
            MissingFieldFound = null,
            ShouldSkipRecord = args => args.Row.Parser.Record.All(String.IsNullOrEmpty)
        };

        using (var reader = new StreamReader("C:\\Users\\eyoung\\Desktop\\parse test files\\Data.csv"))
        using (var csv = new CsvReader(reader, config))
        {
            var sicaGraphDataList = new List<SicaGraphData>();

            while (csv.Read())
            {
                sicaGraphDataList.Add(csv.GetRecord<SicaGraphData>());
            }

            // 转换逻辑写在此处
        }
    }

    public class SicaGraphData
    {
        public string Value1 { get; set; }
        public string Value2 { get; set; }
        public string Value3 { get; set; }
        public string Value4 { get; set; }
        [Name("X (mm)")]
        public string X { get; set; }
        [Name("Y (mm)")]
        public string Y { get; set; }
        [Name("X2 (mm)")]
        public string X2 { get; set; }
        [Name("Y2 (mm)")]
        public string Y2 { get; set; }
        [Name("X3 (mm)")]
        public string X3 { get; set; }
        [Name("Y3 (mm)")]
        public string Y3 { get; set; }
    }
}
解决方案

方案1:每行拆分为多个字典(每组X/Y独立成条)

如果需要把每行中的三组X (mm)/Y (mm)分别作为独立的字典对象(每个字典包含前4个通用值+一组X/Y),可按以下代码实现:

var dictList = new List<Dictionary<string, object>>();

foreach (var data in sicaGraphDataList)
{
    // 提取前4列通用值
    var baseDict = new Dictionary<string, object>
    {
        {"Value1", Convert.ToDouble(data.Value1)},
        {"Value2", Convert.ToDouble(data.Value2)},
        {"Value3", Convert.ToDouble(data.Value3)},
        {"Value4", Convert.ToDouble(data.Value4)}
    };

    // 第一组X/Y
    var dict1 = new Dictionary<string, object>(baseDict)
    {
        {"X (mm)", Convert.ToDouble(data.X)},
        {"Y (mm)", Convert.ToDouble(data.Y)}
    };
    dictList.Add(dict1);

    // 第二组X/Y
    var dict2 = new Dictionary<string, object>(baseDict)
    {
        {"X (mm)", Convert.ToDouble(data.X2)},
        {"Y (mm)", Convert.ToDouble(data.Y2)}
    };
    dictList.Add(dict2);

    // 第三组X/Y
    var dict3 = new Dictionary<string, object>(baseDict)
    {
        {"X (mm)", Convert.ToDouble(data.X3)},
        {"Y (mm)", Convert.ToDouble(data.Y3)}
    };
    dictList.Add(dict3);
}

说明:

  • 将字符串类型的数值转为double,更适配MongoDB的数值存储需求
  • 每行数据生成3个字典对象,完整保留每组X/Y的独立数据关系

方案2:重复X/Y转为数组(每行对应一个字典)

如果希望每行数据对应一个字典,重复的X (mm)/Y (mm)以数组形式存储,可按以下代码实现:

var dictList = new List<Dictionary<string, object>>();

foreach (var data in sicaGraphDataList)
{
    var dict = new Dictionary<string, object>
    {
        {"Value1", Convert.ToDouble(data.Value1)},
        {"Value2", Convert.ToDouble(data.Value2)},
        {"Value3", Convert.ToDouble(data.Value3)},
        {"Value4", Convert.ToDouble(data.Value4)},
        {"X (mm)", new[] {
            Convert.ToDouble(data.X), 
            Convert.ToDouble(data.X2), 
            Convert.ToDouble(data.X3)
        }},
        {"Y (mm)", new[] {
            Convert.ToDouble(data.Y), 
            Convert.ToDouble(data.Y2), 
            Convert.ToDouble(data.Y3)
        }}
    };
    dictList.Add(dict);
}

说明:

  • 重复列的值封装为double[]数组,保证字典键的唯一性
  • 适合需要保留整行数据结构的场景,MongoDB原生支持数组类型存储

方案3:反射自动映射(适配扩展X/Y组)

如果后续可能新增更多X/Y组,可通过反射自动识别属性,避免硬编码:

var dictList = new List<Dictionary<string, object>>();
var props = typeof(SicaGraphData).GetProperties();

foreach (var data in sicaGraphDataList)
{
    // 自动提取Value开头的通用属性
    var baseDict = props
        .Where(p => p.Name.StartsWith("Value"))
        .ToDictionary(p => p.Name, p => (object)Convert.ToDouble(p.GetValue(data)));

    // 自动分组X/Y属性
    var xProps = props.Where(p => p.Name.StartsWith("X")).OrderBy(p => p.Name).ToList();
    var yProps = props.Where(p => p.Name.StartsWith("Y")).OrderBy(p => p.Name).ToList();

    for (int i = 0; i < xProps.Count; i++)
    {
        var dict = new Dictionary<string, object>(baseDict)
        {
            {"X (mm)", Convert.ToDouble(xProps[i].GetValue(data))},
            {"Y (mm)", Convert.ToDouble(yProps[i].GetValue(data))}
        };
        dictList.Add(dict);
    }
}

说明:

  • 通过反射自动识别属性,新增X/Y组时无需修改转换逻辑
  • 按属性名称排序,确保X/Y组的对应关系准确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 00:22:52