I'd like to take a HashSet<String>
and elegantly convert it to a string. I can iterate like so:
HashSet<String> words = new HashSet<string>() { "alpha", "beta", "delta" };
string joined = "";
foreach (var w in words)
joined += w + ",";
if(joined.Length > 0)
joined = joined.SubString(0,joined.Length-1); // remove final comma
Is there a LinQ
way to do this elegantly and efficiently?
The only way I can think of doing this is by converting it to an array first:
HashSet<String> words = new HashSet<string>() { "alpha", "beta", "delta" };
string joined = String.Join(",",words开发者_开发问答.ToArray());
But, then I'm doing a double conversion. Would there be some handy-dandy LinQ expression that's efficient and clear?
ANSWER 1 (from marr's idea)
public static string JoinItems(this IEnumerable<string> items, string joiner) {
StringBuilder sb = new StringBuilder("");
foreach (var i in items)
sb.AppendFormat("{0}{1}",i,joiner);
if(sb.Length>0)
return sb.Remove(sb.Length - joiner.Length, joiner.Length).ToString();
else
return sb.ToString();
}
ANSWER 2 using an Enumerator (from Martin's solution)
public static string JoinItems<T>(this IEnumerable<T> items, string delim) {
var sb = new StringBuilder();
var i = items.GetEnumerator();
if (i.MoveNext()) {
sb.Append(i.Current);
while (i.MoveNext()) {
sb.Append(delim);
sb.Append(i.Current);
}
}
return sb.ToString();
}
I took your method and modified it to not need to remove the last comma. I also changed the AppendFormat
to just Append
because it avoids all the work of parsing the format each time.
public static string JoinItems(this IEnumerable<string> items, string joiner)
{
StringBuilder sb = new StringBuilder();
string delim = "";
foreach (var i in items)
{
sb.Append(delim);
sb.Append(i);
delim = joiner;
}
return sb.ToString();
}
This will do the trick without extra copies or checks on each iteration:
String JoinItems<T>(IEnumerable<T> items) {
var stringBuilder = new StringBuilder();
var i = items.GetEnumerator();
if (i.MoveNext()) {
stringBuilder.Append(i.Current);
while (i.MoveNext()) {
stringBuilder.Append(", ");
stringBuilder.Append(i.Current);
}
}
return stringBuilder.ToString();
}
I don't see the double conversion in your String.Join() line. I see one conversion ToArray(), which is not terrible, and then it executes String.Join(), which performs well.
There is a String.Join() in .Net 4 that takes an IEnumerable that will work without the conversion. If you're using an older framework version, you can write your own extension method for string that takes a separator as the "this" parameter then joins an IEnumerable. Be sure and use stringbuilder for performance.
精彩评论