C# 如何将C中的Dictionary转换为以键为标题的csv?
我有一本字典,像:C# 如何将C中的Dictionary转换为以键为标题的csv?,c#,linq,dictionary,C#,Linq,Dictionary,我有一本字典,像: { key1 : List1 {value1a, value2a}, key2 : List2 {value1b, value2b}, ... } 我如何将其放入csv中,看起来像: key1,key2 value1a,value1b value2a,value2b ... 我已经尝试过首先将其转换为数据表,但我的Linq基础知识遇到了问题 dataTable.Columns.AddRange(dataDictionary .Keys .Sele
{
key1 : List1 {value1a, value2a},
key2 : List2 {value1b, value2b},
...
}
我如何将其放入csv中,看起来像:
key1,key2
value1a,value1b
value2a,value2b
...
我已经尝试过首先将其转换为数据表,但我的Linq基础知识遇到了问题
dataTable.Columns.AddRange(dataDictionary
.Keys
.Select(x => new DataColumn(x, dataDictionary[x])).ToArray());
首先,你得到下面的错误
dataDictionary[x] List<string> can't be converted to System.Type.
其次,下面是假设每个列表长度相同的代码
using System.IO;
using System.Linq;
using System.Text;
using System;
using System.Collections.Generic;
using System.Data;
class Program
{
static void Main(string[] args)
{
Dictionary<string, List<string>> values = new Dictionary<string, List<string>>();
values.Add("key1", new List<string>() { "value1a", "value2a" });
values.Add("key2", new List<string>() { "value1b", "value2b" });
DataTable dataTable = new DataTable();
dataTable.Columns.AddRange(values.Keys.Select(x => new DataColumn(x)).ToArray());
var totalColumns = dataTable.Columns.Count;
for(int i = 0; i < totalColumns; i++)
{
DataRow dataRow = dataTable.NewRow();
int fieldNumber = 0;
foreach(var item in values)
{
dataRow[fieldNumber] = values[item.Key][i];
fieldNumber++;
}
dataTable.Rows.Add(dataRow);
}
dataTable.WriteToCsvFile("D://Test.csv");
}
}
public static class Extension
{
public static void WriteToCsvFile(this DataTable dataTable, string filePath)
{
var content = dataTable.GenerateCsvBytes();
File.WriteAllBytes(filePath, content);
}
public static byte[] GenerateCsvBytes(this DataTable dataTable)
{
StringBuilder fileContent = new StringBuilder();
foreach (var col in dataTable.Columns)
{
fileContent.Append(col.ToString() + ",");
}
fileContent.Replace(",", Environment.NewLine, fileContent.Length - 1, 1);
foreach (DataRow dr in dataTable.Rows)
{
foreach (var column in dr.ItemArray)
{
fileContent.Append("\"" + column.ToString() + "\",");
}
fileContent.Replace(",", Environment.NewLine, fileContent.Length - 1, 1);
}
return Encoding.ASCII.GetBytes(fileContent.ToString());
}
}
如果您正在寻找csv,例如csv文件,而不是数据表,您可以直接实现csv行生成器:
代码:
在您将csv写入文件的情况下,您可以将其作为
File.WriteAllLines(@"c:\demo.csv", ToCsv(myDictionary));
如果data.Keys.Count!=data.Values[0]。计数
嘿,纳扬,这真的很棒。我认为这只是添加尽可能多的行和列,但这只适用于这个2x2示例。是否可以修改for循环以根据列表长度填充行?@MarkMcGown如果键的数量与列表长度不同,如何获得CSV?@NetMage列表长度将成为该列表的键作为标题的列的行数。@MarkMcGown抱歉,我不认为这是可以理解的。也许在你的问题上再加几个例子。在CSV文件中,所有列的长度都相同,在CSV文件中,列的数量等于键的数量。如果您选择将字段放入类或结构中,您可能会发现这很有用。然而,它似乎是针对硬编码列的。
public DataColumn(string columnName, Type dataType)
using System.IO;
using System.Linq;
using System.Text;
using System;
using System.Collections.Generic;
using System.Data;
class Program
{
static void Main(string[] args)
{
Dictionary<string, List<string>> values = new Dictionary<string, List<string>>();
values.Add("key1", new List<string>() { "value1a", "value2a" });
values.Add("key2", new List<string>() { "value1b", "value2b" });
DataTable dataTable = new DataTable();
dataTable.Columns.AddRange(values.Keys.Select(x => new DataColumn(x)).ToArray());
var totalColumns = dataTable.Columns.Count;
for(int i = 0; i < totalColumns; i++)
{
DataRow dataRow = dataTable.NewRow();
int fieldNumber = 0;
foreach(var item in values)
{
dataRow[fieldNumber] = values[item.Key][i];
fieldNumber++;
}
dataTable.Rows.Add(dataRow);
}
dataTable.WriteToCsvFile("D://Test.csv");
}
}
public static class Extension
{
public static void WriteToCsvFile(this DataTable dataTable, string filePath)
{
var content = dataTable.GenerateCsvBytes();
File.WriteAllBytes(filePath, content);
}
public static byte[] GenerateCsvBytes(this DataTable dataTable)
{
StringBuilder fileContent = new StringBuilder();
foreach (var col in dataTable.Columns)
{
fileContent.Append(col.ToString() + ",");
}
fileContent.Replace(",", Environment.NewLine, fileContent.Length - 1, 1);
foreach (DataRow dr in dataTable.Rows)
{
foreach (var column in dr.ItemArray)
{
fileContent.Append("\"" + column.ToString() + "\",");
}
fileContent.Replace(",", Environment.NewLine, fileContent.Length - 1, 1);
}
return Encoding.ASCII.GetBytes(fileContent.ToString());
}
}
key1,key2
value1a,value1b
value2a,value2b
using System.Linq;
...
private static IEnumerable<string> ToCsv(Dictionary<string, List<String>> data) {
// Quotation if required: 123,45 -> "123,45"; a"bc -> "a""bc"
string Quote(string value) => string.IsNullOrEmpty(value)
? "" : value.Contains(',') || value.Contains('"')
? "\"" + value.Replace("\"", "\"\'") + "\""
: value;
int rowCount = data.Max(pair => pair.Value.Count);
// Captions
yield return string.Join(",", data.Select(pair => Quote(pair.Key)));
// Rows one after one
for (int r = 0; r < rowCount; ++r)
yield return string.Join(",", data
.Select(pair => Quote(r < pair.Value.Count ? pair.Value[r] : "")));
}
Dictionary<string, List<string>> data = new Dictionary<string, List<string>>() {
{ "column1", new List<string>() { "C1_A", "C1_B"} },
{ "column2", new List<string>() { "C2_A", "C2_B", "C2_C"} },
{ "column3", new List<string>() { } },
{ "column4", new List<string>() { "C4_A" } },
};
// Generate all lines of the csv and combine them with \r\n:
string csvText = string.Join(Environment.NewLine, ToCsv(data));
Console.Write(csvText);
column1,column2,column3,column4
C1_A,C2_A,,C4_A
C1_B,C2_B,,
,C2_C,,
File.WriteAllLines(@"c:\demo.csv", ToCsv(myDictionary));
var keys = data.Keys;
Console.WriteLine(String.Join(",", keys));
for (int j1 = 0; j1 < keys.Count; ++j1)
Console.WriteLine(String.Join(",", data.Values.Select(v => v[j1])));