创建一个逗号分隔的列表从IList<string>或IENumable<string>

IList<string>IEnumerable<string>创建逗号分隔的字符串值列表的最干净方法是什么?

String.Join(...)string[]进行操作,因此当IList<string>IEnumerable<string>等类型无法轻松转换为字符串数组时,使用起来可能很麻烦。

858286 次浏览

. net4+

IList<string> strings = new List<string>{"1","2","testing"};string joined = string.Join(",", strings);

Detail&Pres. Net 4.0解决方案

IEnumerable<string>可以使用LINQ(. NET 3.5)轻松转换为字符串数组非常

IEnumerable<string> strings = ...;string[] array = strings.ToArray();

如果您需要,编写等效的帮助器方法很容易:

public static T[] ToArray(IEnumerable<T> source){return new List<T>(source).ToArray();}

然后这样称呼它:

IEnumerable<string> strings = ...;string[] array = Helpers.ToArray(strings);

然后您可以调用string.Join。当然,您不能使用helper方法:

// C# 3 and .NET 3.5 way:string joined = string.Join(",", strings.ToArray());// C# 2 and .NET 2.0 way:string joined = string.Join(",", new List<string>(strings).ToArray());

后者是有点一口虽然:)

这可能是最简单的方法,也非常高效——还有其他关于性能的问题,包括(但不限于)这一个

从. NET 4.0开始,string.Join中提供了更多重载,因此您实际上只需编写:

string joined = string.Join(",", strings);

更简单:)

您可以在ListsIEnumerables上使用.ToArray(),然后根据需要使用String.Join()

您可以使用ToArray将IList转换为数组,然后在数组上运行string.join命令。

Dim strs As New List(Of String)Dim arr As Arrayarr = strs.ToArray

我能想到的最简单的方法是使用LINQAggregate方法:

string commaSeparatedList = input.Aggregate((a, x) => a + ", " + x)

可以使用. NET 3.5中的Linq扩展轻松将它们转换为数组。

   var stringArray = stringList.ToArray();

我们有一个效用函数,类似这样:

public static string Join<T>( string delimiter,IEnumerable<T> collection, Func<T, string> convert ){return string.Join( delimiter,collection.Select( convert ).ToArray() );}

它可以很容易地用于加入大量的集合:

int[] ids = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233};
string csv = StringUtility.Join(",", ids, i => i.ToString() );

请注意,我们在lambda之前有集合参数,因为智能感知然后会获取集合类型。

如果你已经有一个字符串的枚举,你需要做的就是ToArray:

string csv = string.Join( ",", myStrings.ToArray() );

在使用其他人列出的方法之一将其转换为数组后,您还可以使用以下内容:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO;using System.Net;using System.Configuration;
namespace ConsoleApplication{class Program{static void Main(string[] args){CommaDelimitedStringCollection commaStr = new CommaDelimitedStringCollection();string[] itemList = { "Test1", "Test2", "Test3" };commaStr.AddRange(itemList);Console.WriteLine(commaStr.ToString()); //Outputs Test1,Test2,Test3Console.ReadLine();}}}

编辑:这里是另一个例子

我写了一些扩展方法来以高效的方式完成它:

    public static string JoinWithDelimiter(this IEnumerable<String> that, string delim) {var sb = new StringBuilder();foreach (var s in that) {sb.AppendToList(s,delim);}
return sb.ToString();}

这取决于

    public static string AppendToList(this String s, string item, string delim) {if (s.Length == 0) {return item;}
return s+delim+item;}

到这个讨论有点晚,但这是我的贡献fwiw。我有一个IList<Guid> OrderIds要转换为CSV字符串,但以下是通用的,并且可以与其他类型一起使用:

string csv = OrderIds.Aggregate(new StringBuilder(),(sb, v) => sb.Append(v).Append(","),sb => {if (0 < sb.Length) sb.Length--; return sb.ToString();});

简短而甜蜜,使用StringBuilder构建新字符串,将StringBuilder长度缩小一以删除最后一个逗号并返回CSV字符串。

我已经更新了它,使用多个Append()来添加字符串+逗号。从James的反馈中,我使用Reflector来查看StringBuilder.AppendFormat()。原来AppendFormat()使用StringBuilder来构造格式字符串,这使得它在这种情况下的效率低于仅使用多个Appends()

仅供参考,. NET 4.0版本的string.Join()有一些额外过载,可以使用IEnumerable而不仅仅是数组,包括一个可以处理任何类型T的数组:

public static string Join(string separator, IEnumerable<string> values)public static string Join<T>(string separator, IEnumerable<T> values)

这是另一种扩展方法:

    public static string Join(this IEnumerable<string> source, string separator){return string.Join(separator, source);}

我的答案类似于上面的聚合解决方案,但应该不那么重调用堆栈,因为没有显式委托调用:

public static string ToCommaDelimitedString<T>(this IEnumerable<T> items){StringBuilder sb = new StringBuilder();foreach (var item in items){sb.Append(item.ToString());sb.Append(',');}if (sb.Length >= 1) sb.Length--;return sb.ToString();}

当然,可以将签名扩展为独立于分隔符的。我真的不喜欢sb. Remove()调用,我想将其重构为IENumable上的一个直接的同时循环,并使用MoveNext()来确定是否写逗号。如果我遇到它,我会摆弄一下并发布该解决方案。


这是我最初想要的:

public static string ToDelimitedString<T>(this IEnumerable<T> source, string delimiter, Func<T, string> converter){StringBuilder sb = new StringBuilder();var en = source.GetEnumerator();bool notdone = en.MoveNext();while (notdone){sb.Append(converter(en.Current));notdone = en.MoveNext();if (notdone) sb.Append(delimiter);}return sb.ToString();}

不需要临时数组或列表存储,也不需要StringBuilderRemove()Length--黑客。

在我的框架库中,我对这个方法签名做了一些变化,每个组合都包括delimiterconverter参数,分别使用","x.ToString()作为默认值。

有点奇怪,但它奏效了:

string divisionsCSV = String.Join(",", ((List<IDivisionView>)divisions).ConvertAll<string>(d => d.DivisionID.ToString("b")).ToArray());

在给它转换器之后从List中给你一个CSV(在本例中为d=>d. DivisionID. ToString("b"))。

Hacky但作品-也许可以制作成一种扩展方法?

这是我做的方式,使用我在其他语言中做的方式:

private string ToStringList<T>(IEnumerable<T> list, string delimiter){var sb = new StringBuilder();string separator = String.Empty;foreach (T value in list){sb.Append(separator).Append(value);separator = delimiter;}return sb.ToString();}

我认为创建以逗号分隔的字符串值列表的最干净的方法很简单:

string.Join<string>(",", stringEnumerable);

下面是一个完整的例子:

IEnumerable<string> stringEnumerable= new List<string>();stringList.Add("Comma");stringList.Add("Separated");
string.Join<string>(",", stringEnumerable);

不需要创建辅助函数,它内置在. NET 4.0及更高版本中。

希望这是最简单的方法

 string Commaseplist;string[] itemList = { "Test1", "Test2", "Test3" };Commaseplist = string.join(",",itemList);Console.WriteLine(Commaseplist); //Outputs Test1,Test2,Test3

在阅读本文之前,我刚刚解决了这个问题。我的解决方案如下所示:

   private static string GetSeparator<T>(IList<T> list, T item){return (list.IndexOf(item) == list.Count - 1) ? "" : ", ";}

叫做:

List<thing> myThings;string tidyString;
foreach (var thing in myThings){tidyString += string.format("Thing {0} is a {1}", thing.id, thing.name) + GetSeparator(myThings, thing);}

我也可以像这样轻松地表达,也会更有效率:

string.Join(“,”, myThings.Select(t => string.format(“Thing {0} is a {1}”, t.id, t.name));

具体需要什么时候我们应该包围by,by ex:

        string[] arr = { "jj", "laa", "123" };List<string> myList = arr.ToList();
// 'jj', 'laa', '123'Console.WriteLine(string.Join(", ",myList.ConvertAll(m =>string.Format("'{0}'", m)).ToArray()));

我在寻找一个好的C#方法来连接字符串时进行了这个讨论,就像使用MySql方法CONCAT_WS()一样。此方法与string.Join()方法的不同之处在于,如果字符串为NULL或空,它不会添加分隔符符号。

CONCAT_WS(',', tbl. Lastname, tbl. Firstname)

如果first name为空,则仅返回Lastname,而

加入(", ", strLastname, strFirstname)

将在相同的情况下返回strLastname + ", "

想要第一个行为,我写了以下方法:

    public static string JoinStringsIfNotNullOrEmpty(string strSeparator, string strA, string strB, string strC = ""){return JoinStringsIfNotNullOrEmpty(strSeparator, new[] {strA, strB, strC});}
public static string JoinStringsIfNotNullOrEmpty(string strSeparator, string[] arrayStrings){if (strSeparator == null)strSeparator = "";if (arrayStrings == null)return "";string strRetVal = arrayStrings.Where(str => !string.IsNullOrEmpty(str)).Aggregate("", (current, str) => current + (str + strSeparator));int trimEndStartIndex = strRetVal.Length - strSeparator.Length;if (trimEndStartIndex>0)strRetVal = strRetVal.Remove(trimEndStartIndex);return strRetVal;}

由于我在搜索加入对象列表的特定属性(而不是它的ToString())时到达这里,这里是对接受的答案的补充:

var commaDelimited = string.Join(",", students.Where(i => i.Category == studentCategory).Select(i => i.FirstName));

通过性能比较,获胜者是“Loop it, sb. Append it, and do back”。实际上“可枚举和手动移动下一步”是一样好的(考虑stddev)。

BenchmarkDotNet=v0.10.5, OS=Windows 10.0.14393Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4Frequency=3233539 Hz, Resolution=309.2587 ns, Timer=TSC[Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0Clr    : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0Core   : .NET Core 4.6.25009.03, 64bit RyuJIT

Method |  Job | Runtime |     Mean |     Error |    StdDev |      Min |      Max |   Median | Rank |  Gen 0 | Allocated |---------------------- |----- |-------- |---------:|----------:|----------:|---------:|---------:|---------:|-----:|-------:|----------:|StringJoin |  Clr |     Clr | 28.24 us | 0.4381 us | 0.3659 us | 27.68 us | 29.10 us | 28.21 us |    8 | 4.9969 |   16.3 kB |SeparatorSubstitution |  Clr |     Clr | 17.90 us | 0.2900 us | 0.2712 us | 17.55 us | 18.37 us | 17.80 us |    6 | 4.9296 |  16.27 kB |SeparatorStepBack |  Clr |     Clr | 16.81 us | 0.1289 us | 0.1206 us | 16.64 us | 17.05 us | 16.81 us |    2 | 4.9459 |  16.27 kB |Enumerable |  Clr |     Clr | 17.27 us | 0.0736 us | 0.0615 us | 17.17 us | 17.36 us | 17.29 us |    4 | 4.9377 |  16.27 kB |StringJoin | Core |    Core | 27.51 us | 0.5340 us | 0.4995 us | 26.80 us | 28.25 us | 27.51 us |    7 | 5.0296 |  16.26 kB |SeparatorSubstitution | Core |    Core | 17.37 us | 0.1664 us | 0.1557 us | 17.15 us | 17.68 us | 17.39 us |    5 | 4.9622 |  16.22 kB |SeparatorStepBack | Core |    Core | 15.65 us | 0.1545 us | 0.1290 us | 15.45 us | 15.82 us | 15.66 us |    1 | 4.9622 |  16.22 kB |Enumerable | Core |    Core | 17.00 us | 0.0905 us | 0.0654 us | 16.93 us | 17.12 us | 16.98 us |    3 | 4.9622 |  16.22 kB |

代码:

public class BenchmarkStringUnion{List<string> testData = new List<string>();public BenchmarkStringUnion(){for(int i=0;i<1000;i++){testData.Add(i.ToString());}}[Benchmark]public string StringJoin(){var text = string.Join<string>(",", testData);return text;}[Benchmark]public string SeparatorSubstitution(){var sb = new StringBuilder();var separator = String.Empty;foreach (var value in testData){sb.Append(separator).Append(value);separator = ",";}return sb.ToString();}
[Benchmark]public string SeparatorStepBack(){var sb = new StringBuilder();foreach (var item in testData)sb.Append(item).Append(',');if (sb.Length>=1)sb.Length--;return sb.ToString();}
[Benchmark]public string Enumerable(){var sb = new StringBuilder();var e = testData.GetEnumerator();bool  moveNext = e.MoveNext();while (moveNext){sb.Append(e.Current);moveNext = e.MoveNext();if (moveNext)sb.Append(",");}return sb.ToString();}}

https://github.com/dotnet/BenchmarkDotNet被使用

如果你想加入的字符串在对象列表中,那么你也可以这样做:

var studentNames = string.Join(", ", students.Select(x => x.name));

要从IList<string>IEnumerable<string>创建逗号分隔的列表,除了使用string.Join()之外,您还可以使用StringBuilder.AppendJoin方法:

new StringBuilder().AppendJoin(", ", itemList).ToString();

$"{new StringBuilder().AppendJoin(", ", itemList)}";

我知道现在回答这个问题有点晚了,但在这里寻找这个问题的答案可能会有所帮助。

你可以像下面这样做:

var finalString = String.Join(",", ExampleArrayOfObjects.Where(newList => !String.IsNullOrEmpty(newList.TestParameter)).Select(newList => newList.TestParameter));

使用示例ArrayOfObject.在这里我们将创建具有非空值的新对象列表

然后进一步使用。在新的对象列表上选择以“,”作为分隔符加入并制作最终字符串。