我有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
或许你知道更好的方法吗?我必须迭代这个列表,字段(列)的数量是可变的。
答案 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;
您明确要求List<Dictionary<string, string>>
,这就是我提供的答案。如果数据类符合您当前的情况,那么您的数据类(其属性与您期望找到的列匹配)会好得多。
您可能想要添加一些空检查和尝试捕获。为了简洁起见,我从我的例子中省略了它们。
请注意,我的示例仅根据找到了多少个标题来解析单元格。如果您的某些数据行的单元格数多于标题数,则会忽略这些单元格。
有LINQ方法以类似的方式解决这个问题,但我选择了foreach
,因为它更容易阅读,我认为理解算法的意图更重要。
如果您要解析一个庞大的CSV文件,那么使用StreamReader
逐行读取文件可能会更好(因此您不必将所有内容都放入一次性记忆)。 File.ReadAllLines()
适用于“普通”大小的CSV文件。
如果任何行的数据单元少于标题(<换句话说,它发生在IndexOutOfRange
时),您将遇到cells.Length < columnHeaders.Length
异常。如果遇到此问题,则需要添加额外的检查,以确保只有标题和标题值存在时才分配值。但是我在示例中省略了它,因为它会混淆(相对简单的)基础算法。
如果您遇到重复标题,那么您将遇到异常(这有点意图,而不是让第二列覆盖字典中第一列的值而不进行大惊小怪)。如果这是您需要避免的问题,请找出您想要完成的操作并添加必要的代码。
Dictionary<string,string>
方法)