CSV文件中的词典列表

时间:2017-09-18 08:55:54

标签: c# list linq dictionary

我有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

或许你知道更好的方法吗?我必须迭代这个列表,字段(列)的数量是可变的。

1 个答案:

答案 0 :(得分:0)

解决方案

这是一种简单的方法,可以返回您想要的内容。我已经评论了解释这种方法的每一步。其中的步骤本身应该很容易理解。

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<Dictionary<string, string>>,这就是我提供的答案。如果数据类符合您当前的情况,那么您的数据类(其属性与您期望找到的列匹配)会好得多。

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

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

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

  5. 如果您要解析一个庞大的CSV文件,那么使用StreamReader逐行读取文件可能会更好(因此您不必将所有内容都放入一次性记忆)。 File.ReadAllLines()适用于“普通”大小的CSV文件。

  6. 如果任何行的数据单元少于标题(<换句话说,它发生在IndexOutOfRange时),您将遇到cells.Length < columnHeaders.Length异常。如果遇到此问题,则需要添加额外的检查,以确保只有标题标题值存在时才分配值。但是我在示例中省略了它,因为它会混淆(相对简单的)基础算法。

  7. 如果您遇到重复标题,那么您将遇到异常(这有点意图,而不是让第二列覆盖字典中第一列的值而不进行大惊小怪)。如果这是您需要避免的问题,请找出您想要完成的操作并添加必要的代码。

    • 是否应忽略第二个(重复)标头,而文件的其余部分仍然正常解析?
    • 您想要存储这两个值吗? (这意味着要远离Dictionary<string,string>方法)
    • 您是要停止解析文件并抛出异常吗?
    • ...