可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Given a list of strings, what is the best method for concatenating these strings into a comma separated list with no comma at the end. (VB.NET or C#) (Using either StringBuilder or String Concat.)
Dim strResult As String = ""
Dim lstItems As New List(Of String)
lstItems.Add("Hello")
lstItems.Add("World")
For Each strItem As String In lstItems
If strResult.Length > 0 Then
strResult = strResult & ", "
End If
strResult = strResult & strItem
Next
MessageBox.Show(strResult)
回答1:
Dim Result As String
Dim Items As New List(Of String)
Items.Add("Hello")
Items.Add("World")
Result = String.Join(",", Items.ToArray())
MessageBox.Show(Result)
If you're really concerned about empty strings, use this join function:
Function Join(ByVal delimiter As String, ByVal items As IEnumerable(Of String), Optional ByVal IgnoreEmptyEntries As Boolean = True) As String
Dim delim As String = ""
Dim result As New Text.StringBuilder("")
For Each item As String In items
If Not IgnoreEmptyEntries OrElse Not String.IsNullOrEmpty(item) Then
result.Append(delim).Append(item)
delim = delimiter
End If
Next
Return result.ToString()
End Function
回答2:
Does the solution have to use a StringBuilder
or the Concat
method?
If not, you could use the static String.Join
method. For example (in C#):
string result = String.Join(",", items.ToArray());
See my very similar question for more details on this.
回答3:
Like this:
lstItems.ToConcatenatedString(s => s, ", ")
If you want to ignore empty strings as in your example:
lstItems
.Where(s => s.Length > 0)
.ToConcatenatedString(s => s, ", ")
The most popular custom aggregate function in my toolbox. I use it every day:
public static class EnumerableExtensions
{
/// <summary>
/// Creates a string from the sequence by concatenating the result
/// of the specified string selector function for each element.
/// </summary>
public static string ToConcatenatedString<T>(
this IEnumerable<T> source,
Func<T, string> stringSelector)
{
return EnumerableExtensions.ToConcatenatedString(source, stringSelector, String.Empty);
}
/// <summary>
/// Creates a string from the sequence by concatenating the result
/// of the specified string selector function for each element.
/// </summary>
/// <param name="separator">The string which separates each concatenated item.</param>
public static string ToConcatenatedString<T>(
this IEnumerable<T> source,
Func<T, string> stringSelector,
string separator)
{
var b = new StringBuilder();
bool needsSeparator = false; // don't use for first item
foreach (var item in source)
{
if (needsSeparator)
b.Append(separator);
b.Append(stringSelector(item));
needsSeparator = true;
}
return b.ToString();
}
}
回答4:
Going on from the String.Join answer, to ignore null/empty strings (and if you are using .NET 3.5) you could use a bit of Linq. e.g.
Dim Result As String
Dim Items As New List(Of String)
Items.Add("Hello")
Items.Add("World")
Result = String.Join(",", Items.ToArray().Where(Function(i) Not String.IsNullOrEmpty(i))
MessageBox.Show(Result)
回答5:
If you don't have to use StringBuilder
or Concat
method you could also use:
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,Test3
Console.ReadLine();
}
}
}
This requires a reference to System.Configuration
回答6:
There are several ways to do this, but they're basically variations on a theme.
Pseudocode:
For Each Item In Collection:
Add Item To String
If Not Last Item, Add Comma
A different way that I like a little better is something like this:
For Each Item In Collection:
If Not First Item, Add Comma
Add Item To String
Edit: The reason I like the second way of doing it is that each item stands on its own. Using the first approach, if you modified your logic later so that a subsequent item might not get added, you could end up with a stray comma at the end of the string unless you also made your test in the previous item more intelligent, which is dumb.
回答7:
or you can do:
Separator = ""
For Each Item In Collection
Add Separator + Item To String
Separator = ", "
By setting the separator to an empty string in the first iteration you skip the first comma. One less if statement. This might or might not be more readable depending on what you're used to
回答8:
Would you believe there's a class in the .NET framework which provides this functionality?
public static string ListToCsv<T>(List<T> list)
{
CommaDelimitedStringCollection commaStr = new CommaDelimitedStringCollection();
list.ForEach(delegate(T item)
{
commaStr.Add(item.ToString());
});
return commaStr.ToString();
}
回答9:
Thanks for all of the responses.
It appears that the "proper" answer depends on the context in which the comma separated list is being built. I don't have a neat list of items to use (had to use something for an example...), but I do have an array whose items may or may not be added to the comma seperated list depending on various conditions.
So I chose something to the effect of
strResult = ""
strSeparator = ""
for i as integer = 0 to arrItems.Length - 1
if arrItems(i) <> "test" and arrItems(i) <> "point" then
strResult = strResult & strSeparator & arrItem(i)
strSeparator = ", "
end if
next
As usual, there are numerous methods of doing this. I don't know that any one method deserves more praise or promotion than another. Some are more useful in certain contexts while others satisfy the requirements of different contexts.
Again, thanks to all for your input.
BTW, the original post with the "off the top of my head" code sample is not filtering zero length items, instead it is waiting for the result string to become greater than zero length before adding the comma. Probably not very efficient but I have'nt tested it. Again, it was off the top of my head.
回答10:
Dim strResult As String = ""
Dim separator = ","
Dim lstItems As New List(Of String)
lstItems.Add("Hello")
lstItems.Add("World")
For Each strItem As String In lstItems
strResult = String.Concat(strResult, separator)
Next
strResult = strResult.TrimEnd(separator.ToCharArray())
MessageBox.Show(strResult)
The idea is to use String.TrimEnd() function