This has probably been done before, but I thought I would post my implementation.
Take a given generic list (or something that implements IEnumerable, and convert it to a delimited string.
First, in a static class, (I have a class called GeneralExtensions for just this sort of thing), add this code.
1: public static string ToDelimitedString<T>(this IEnumerable<T> list, string delimiter, Func<T, string> action)
2: {
3: var sb = new System.Text.StringBuilder();
4: foreach (var t in list)
5: {
6: sb.Append(action.Invoke(t));
7: sb.Append( delimiter );
8: }
9: sb.Remove(sb.Length - delimiter.Length, 1);
10:
11: return sb.ToString();
12: }
Now if I have a customer class with a FirstName and LastName properties, like this:
1: public class Customer
2: {
3: public string Id { get; set; }
4: public string FirstName { get; set; }
5: public string LastName { get; set; }
6: }
And I have a list of them, and want to convert them to a coma delimited list, I would do it like this:
1: var list = new List<Customer>();
2: list.Add(new Customer { FirstName="Tom", LastName="Bin" });
3: list.Add(new Customer { FirstName="John", LastName"Doe" });
4:
5: string result = list.ToDelimitedString(",", c => c.FirstName + " " + c.LastName);
The result will look like this: “Tom Bin, John Doe”
Chris,
I’m curious as to why do you use a custom delegate when you can use a Func? Also, is there a reason for action.Invoke(t) rather than action(t)?
Terry
Hey, it ate my signs …
Func should really be Func<T, string>
And in case that didn’t work a Func that takes a T and returns a string.
sb.Remove(sb.Length – 1, 1); should be
sb.Remove(sb.Length – delimiter.Length, delimiter.Length);
And I always use the string.Join method, first argument is your delimiter, second argument is a string array.
return string.Join(delimiter, list.Select(action).ToArray());
@Terry: I forgot about Func (I remembered Action, but forgot about Func). OK, fixed my code, retested, still works. Thank you for the suggestion.
@Steve: Missed the delimiter.Length, thank you.
I looked at string.Join, and the reason I shyed away from it was because of the ToArray. The ToArray is unlikely to cause problems, but it is slightly more direct in that a separate array does not have to be created.
Which, for the size of the data that I’m parsing, is probably being offset by the use of the StringBuilder.
This is what I get for posting something so quickly…but then again, it is a great way to learn/remember what is possible.
I like the idea of that. What about this (off top of head):
public class Customer
{
//…properties
public string FullName{ get{ return String.Format(“{0} {1}”, FirstName, LastName; } }
}
string result = string.Join(“,”, customers.Select(c=>c.FullName).ToArray() );
Something like that, anyway. Or if you don’t like FulllName, would this work?
string result = string.Join(“,”, customers.Select(c=>String.Format(“{0} {1}”, c.FirstName, c.LastName ).ToArray() );
I also write an extension method for string to make String.Format more fluent. You can then do this:
string fullName = “{0} {1}”.QuickFormat(c.Forename, c.Surname);
Doh! After posting I saw the previous comment mentioned all this. Soz.
@tobin: ok, I really like the idea of the quick format. I have to do that one now.
public static string QuickFormat(this string format, params object[] args )
{
return string.Format(format, args);
}