【问题标题】:List of dictionaries from CSV fileCSV 文件中的字典列表
【发布时间】:2017-09-18 08:55:54
【问题描述】:

我有 csv 文件,例如:

col1;col2
val1;val2
val3;val4

我想创建字典列表,如下所示:

[0] k:col1, v:val1
    k:col2, v:val2
[1] k:col1, v:val3
    k:col2, v:val4

或者你知道更好的方法?我必须遍历这个列表,并且字段(列)的数量是可变的。

【问题讨论】:

  • 如果您能向我们描述您想要实现的目标以及到目前为止您已经尝试过什么,有多少数据......我们也许可以为您提供专业知识做:)
  • 我想遍历这个 CSV 文件,但不知道怎么做。我不想为行创建类,因为该文件将来会有不同的列数。我需要一个通用且快速的解决方案。
  • 为什么是字典?您可以使用List<string[]>DataTable

标签: c# list linq dictionary


【解决方案1】:

解决方案

这里有一个简单的方法可以返回你想要的东西。我已经评论了解释该方法的每一步。这些步骤本身应该很容易理解。

var lines = File.ReadAllLines("c:\\myfile.csv");

//1. Read all headers
string[] columnHeaders = lines[0].Split(';');

//2. Instantiate your end result variable.
List<Dictionary<string, string>> linesAsDictionaries = new List<Dictionary<string, string>>();

//3. Process all lines (except the header row!)
foreach(var line in lines.Skip(1))
{
    //3.1 Instantiate the resulting dictionary
    var newDict = new Dictionary<string, string>();

    //3.2 Split the data
    var cells = line.Split(';');

    //3.3 Add an entry for each retrieved header.
    for (int i = 0; i < columnHeaders.Length; i++)
    {
        newDict.Add(columnHeaders[i], cells[i]);
    }

    //3.4 Add the dictionary to the resulting list
    linesAsDictionaries.Add(newDict);
}

return linesAsDictionaries;

一些注意事项

  1. 您明确要求List&lt;Dictionary&lt;string, string&gt;&gt;,这就是我提供的答案。如果它适合您当前的场景,那么使用数据类(其属性与您期望找到的列匹配)会更好。

  2. 您可能想要添加一些空检查和尝试捕获。为了简洁起见,我在示例中省略了它们。

  3. 请注意,我的示例仅根据 找到多少标题 来解析单元格。如果您的某些数据行的单元格比标题多,这些单元格将被忽略。

  4. 有 LINQ 方法可以以类似的方式解决此问题,但我选择了 foreach,因为它更易于阅读,而且我认为理解 算法的意图 是更重要。

  5. 如果您要解析大型 CSV 文件,最好使用 StreamReader 逐行读取文件(这样您就不必将所有内容全部存入内存)立刻)。 File.ReadAllLines() 足以处理“正常”大小的 CSV 文件。

  6. 如果任何行的数据单元格数少于标题数,您将遇到IndexOutOfRange 异常(换句话说,当cells.Length &lt; columnHeaders.Length 时会发生这种情况)。如果遇到这种情况,则需要添加额外的检查以确保仅在标题 单元格值都存在时才分配值。但我在示例中省略了它,因为它会混淆(相对简单的)底层算法。

  7. 如果您遇到重复标题,那么您将遇到异常(这在某种程度上是故意的,而不是让第二列覆盖字典中第一列的值而不大惊小怪)。如果这是您需要避免的问题,请弄清楚您想要做什么并添加必要的代码。

    • 是否应该忽略第二个(重复的)标题,而文件的其余部分仍按正常方式解析?
    • 是否要存储这两个值? (这意味着放弃 Dictionary&lt;string,string&gt; 方法)
    • 是否要停止解析文件并引发异常?
    • ...

【讨论】:

  • 感谢您的解决方案!对于我的需要就足够了:) PS。您跳过了 'linesAsDictionaries.Add(newDict);'在“foreach”循环结束时;)
  • @cs9112:很好!在构建类似的解决方案时,我总是倾向于忘记这一行;)我认为这是因为 LINQ 等效项不再需要显式添加,所以我已经失去了编写一个的习惯。
猜你喜欢
  • 2014-06-30
  • 2015-09-16
  • 2017-05-13
  • 2020-09-26
  • 2023-04-10
  • 2014-03-01
  • 2019-02-01
  • 1970-01-01
相关资源
最近更新 更多