Den*_*ail 129 c# generics .net-3.5
我有一个整数值列表(List),并希望生成一个逗号分隔值的字符串.这是列表输出中的所有项目到单个逗号分隔列表.
我的想法...... 1.将列表传递给方法.2.使用stringbuilder迭代列表并附加逗号3.测试最后一个字符,如果是逗号,则删除它.
你的想法是什么?这是最好的方法吗?
如果我不仅要处理整数(我当前的计划),还要处理字符串,longs,double,bools等等,我的代码将如何变化?我想让它接受任何类型的列表.
jas*_*son 232
框架已经为我们做了很多事情.
List<int> myValues;
string csv = String.Join(",", myValues.Select(x => x.ToString()).ToArray());
Run Code Online (Sandbox Code Playgroud)
对于一般情况:
IEnumerable<T> myList;
string csv = String.Join(",", myList.Select(x => x.ToString()).ToArray());
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,它实际上并没有什么不同.请注意,如果包含逗号,您可能需要实际包装x.ToString()引号(即"\"" + x.ToString() + "\"")x.ToString().
有关这方面略有变化的有趣读物:请参阅Eric Lippert博客上的Comma Quibbling.
注意:这是在.NET 4.0正式发布之前编写的.现在我们可以说
IEnumerable<T> sequence;
string csv = String.Join(",", sequence);
Run Code Online (Sandbox Code Playgroud)
使用过载String.Join<T>(string, IEnumerable<T>).此方法将自动将每个元素投影x到x.ToString().
Kri*_*hna 12
在3.5,我仍然能够做到这一点.它更简单,不需要lambda.
String.Join(",", myList.ToArray<string>());
Run Code Online (Sandbox Code Playgroud)
Wha*_*sit 10
您可以创建一个可以在任何IEnumerable上调用的扩展方法:
public static string JoinStrings<T>(
this IEnumerable<T> values, string separator)
{
var stringValues = values.Select(item =>
(item == null ? string.Empty : item.ToString()));
return string.Join(separator, stringValues.ToArray());
}
Run Code Online (Sandbox Code Playgroud)
然后你可以在原始列表上调用该方法:
string commaSeparated = myList.JoinStrings(", ");
Run Code Online (Sandbox Code Playgroud)
小智 8
我在这篇文章中对其进行了深入解释。我将简单地将代码粘贴到此处。
这是创建标题行的方法。它使用属性名称作为列名称。
private static void CreateHeader<T>(List<T> list, StreamWriter sw)
{
PropertyInfo[] properties = typeof(T).GetProperties();
for (int i = 0; i < properties.Length - 1; i++)
{
sw.Write(properties[i].Name + ",");
}
var lastProp = properties[properties.Length - 1].Name;
sw.Write(lastProp + sw.NewLine);
}
Run Code Online (Sandbox Code Playgroud)
此方法创建所有值行
private static void CreateRows<T>(List<T> list, StreamWriter sw)
{
foreach (var item in list)
{
PropertyInfo[] properties = typeof(T).GetProperties();
for (int i = 0; i < properties.Length - 1; i++)
{
var prop = properties[i];
sw.Write(prop.GetValue(item) + ",");
}
var lastProp = properties[properties.Length - 1];
sw.Write(lastProp.GetValue(item) + sw.NewLine);
}
}
Run Code Online (Sandbox Code Playgroud)
这是将它们组合在一起并创建实际文件的方法。
public static void CreateCSV<T>(List<T> list, string filePath)
{
using (StreamWriter sw = new StreamWriter(filePath))
{
CreateHeader(list, sw);
CreateRows(list, sw);
}
}
Run Code Online (Sandbox Code Playgroud)
你可以用String.Join.
String.Join(
",",
Array.ConvertAll(
list.ToArray(),
element => element.ToString()
)
);
Run Code Online (Sandbox Code Playgroud)
如果任何正文要转换自定义类对象列表而不是字符串列表,则使用类的csv行表示覆盖类的ToString方法.
Public Class MyClass{
public int Id{get;set;}
public String PropertyA{get;set;}
public override string ToString()
{
return this.Id+ "," + this.PropertyA;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,可以使用以下代码将此类列表转换为带有标题列的 CSV
string csvHeaderRow = String.Join(",", typeof(MyClass).GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(x => x.Name).ToArray<string>()) + Environment.NewLine;
string csv= csvHeaderRow + String.Join(Environment.NewLine, MyClass.Select(x => x.ToString()).ToArray());
Run Code Online (Sandbox Code Playgroud)
小智 6
我喜欢一个很好的简单的扩展方法
public static string ToCsv(this List<string> itemList)
{
return string.Join(",", itemList);
}
Run Code Online (Sandbox Code Playgroud)
然后你就可以调用原始列表上的方法:
string CsvString = myList.ToCsv();
Run Code Online (Sandbox Code Playgroud)
比其他一些建议更干净、更容易阅读。
正如@Frank给出的链接中的代码从.NET通用列表创建一个CSV文件时,有一个小问题是,我修改了代码来结束每一行以摆脱它.希望它可以帮助某人.
/// <summary>
/// Creates the CSV from a generic list.
/// </summary>;
/// <typeparam name="T"></typeparam>;
/// <param name="list">The list.</param>;
/// <param name="csvNameWithExt">Name of CSV (w/ path) w/ file ext.</param>;
public static void CreateCSVFromGenericList<T>(List<T> list, string csvCompletePath)
{
if (list == null || list.Count == 0) return;
//get type from 0th member
Type t = list[0].GetType();
string newLine = Environment.NewLine;
if (!Directory.Exists(Path.GetDirectoryName(csvCompletePath))) Directory.CreateDirectory(Path.GetDirectoryName(csvCompletePath));
if (!File.Exists(csvCompletePath)) File.Create(csvCompletePath);
using (var sw = new StreamWriter(csvCompletePath))
{
//make a new instance of the class name we figured out to get its props
object o = Activator.CreateInstance(t);
//gets all properties
PropertyInfo[] props = o.GetType().GetProperties();
//foreach of the properties in class above, write out properties
//this is the header row
sw.Write(string.Join(",", props.Select(d => d.Name).ToArray()) + newLine);
//this acts as datarow
foreach (T item in list)
{
//this acts as datacolumn
var row = string.Join(",", props.Select(d => item.GetType()
.GetProperty(d.Name)
.GetValue(item, null)
.ToString())
.ToArray());
sw.Write(row + newLine);
}
}
}
Run Code Online (Sandbox Code Playgroud)