将对象集合加入逗号分隔的字符串中

在我们的代码中的许多地方,我们都有对象集合,我们需要从中创建以逗号分隔的列表。 集合的类型各不相同:它可能是我们需要某个列的DataTable,或者是List 等。

现在我们遍历集合并使用字符串连接,例如:

string text = ""; string separator = ""; foreach (DataRow row in table.Rows) { text += separator + row["title"]; separator = ", "; } 

这有更好的模式吗? 理想情况下,我希望通过发送函数来从每个对象获取正确的字段/属性/列,我们可以重用一种方法。

 // using System.Collections; // using System.Collections.Generic; // using System.Linq public delegate string Indexer(T obj); public static string concatenate(IEnumerable collection, Indexer indexer, char separator) { StringBuilder sb = new StringBuilder(); foreach (T t in collection) sb.Append(indexer(t)).Append(separator); return sb.Remove(sb.Length - 1, 1).ToString(); } // version for non-generic collections public static string concatenate(IEnumerable collection, Indexer indexer, char separator) { StringBuilder sb = new StringBuilder(); foreach (object t in collection) sb.Append(indexer((T)t)).Append(separator); return sb.Remove(sb.Length - 1, 1).ToString(); } // example 1: simple int list string getAllInts(IEnumerable listOfInts) { return concatenate(listOfInts, Convert.ToString, ','); } // example 2: DataTable.Rows string getTitle(DataRow row) { return row["title"].ToString(); } string getAllTitles(DataTable table) { return concatenate(table.Rows, getTitle, '\n'); } // example 3: DataTable.Rows without Indexer function string getAllTitles(DataTable table) { return concatenate(table.Rows, r => r["title"].ToString(), '\n'); } 
 string.Join(", ", Array.ConvertAll(somelist.ToArray(), i => i.ToString())) 
 static string ToCsv(IEnumerable things, Func toStringMethod) { StringBuilder sb = new StringBuilder(); foreach (T thing in things) sb.Append(toStringMethod(thing)).Append(','); return sb.ToString(0, sb.Length - 1); //remove trailing , } 

使用这样:

 DataTable dt = ...; //datatable with some data Console.WriteLine(ToCsv(dt.Rows, row => row["ColName"])); 

要么:

 List customers = ...; //assume Customer has a Name property Console.WriteLine(ToCsv(customers, c => c.Name)); 

我没有编译器,但理论上它应该工作。 众所周知,理论上,实践和理论都是一样的。 在实践中,他们不是。

我发现string.Join和Lambda Select>有助于编写最小代码。

  List fruits = new List(); fruits.Add("Mango"); fruits.Add("Banana"); fruits.Add("Papaya"); string commaSepFruits = string.Join(",", fruits.Select(f => "'" + f + "'")); Console.WriteLine(commaSepFruits); List ids = new List(); ids.Add(1001); ids.Add(1002); ids.Add(1003); string commaSepIds = string.Join(",", ids); Console.WriteLine(commaSepIds); List customers = new List(); customers.Add(new Customer { Id = 10001, Name = "John" }); customers.Add(new Customer { Id = 10002, Name = "Robert" }); customers.Add(new Customer { Id = 10002, Name = "Ryan" }); string commaSepCustIds = string.Join(", ", customers.Select(cust => cust.Id)); string commaSepCustNames = string.Join(", ", customers.Select(cust => "'" + cust.Name + "'")); Console.WriteLine(commaSepCustIds); Console.WriteLine(commaSepCustNames); Console.ReadLine(); 

在.NET 4中你可以做string.Join(", ", table.Rows.Select(r => r["title"]))

您可以编写一个将IEnumerable转换为逗号分隔字符串的函数

 public string Concat(IEnumerable stringList) { StringBuilder textBuilder = new StringBuilder(); string separator = String.Empty; foreach(string item in stringList) { textBuilder.Append(separator); textBuilder.Append(item); separator = ", "; } return textBuilder.ToString(); } 

然后,您可以使用Linq查询集合/数据集/ etc以提供stringList。

暂且不说:我要做的第一个修改就是使用StringBuilder类而不仅仅是一个String – 它会为你节省资源。

我喜欢Matt Howells在这篇文章中回答 :

我不得不把它变成一个扩展:

 public static string ToCsv(this IEnumerable things, Func toStringMethod) 

用法:[我收到所有电子邮件并将其转换为电子邮件的csv字符串]:

 var list = Session.Find("from User u where u.IsActive = true").Cast(); return list.ToCsv(i => i.Email); 
 string strTest = "1,2,4,6"; string[] Nums = strTest.Split(','); Console.Write(Nums.Aggregate((first, second) => first + "," + second)); //OUTPUT: //1,2,4,6 

这是我最喜欢的问题,并修正了转换为ConvertAll:

 string text = string.Join(", ", Array.ConvertAll(table.Rows.ToArray(), i => i["title"])); 

对于集合,您也可以使用此方法,例如:

 string.Join(", ", contactsCollection.Select(i => i.FirstName); 

您可以选择要分隔的任何属性。