You can use LINQ for a lot more than just conventional querying. Here's some cute code that turns an IEnumerable<T> into a comma-separated string -- using just one LINQ statement.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace CommaSeparated
{
class Program
{
static void Main(string[] args)
{
// Prints "Canada, United States and Mexico"
Console.WriteLine(CommaSeparate(new[] { "Canada", "United States", "Mexico" }));
// Prints "1 and 2"
Console.WriteLine(CommaSeparate(new[] { 1, 2 }));
// Prints "United States"
Console.WriteLine(CommaSeparate(new[] { "United States" }));
// Prints ""
Console.WriteLine(CommaSeparate(new string[] { }));
Console.WriteLine("Press Enter to quit.");
Console.ReadLine();
}
static string CommaSeparate<T>(IEnumerable<T> items)
{
return items.Aggregate(
new StringBuilder(),
(sb, item) => sb.Append(item).Append(", "),
sb => Regex.Replace(
Regex.Replace(sb.ToString(), ", $", ""), // Remove the final comma and space.
", ([^,]+)$", // Change the penultimate comma...
@" and $1")); // ...to " and".
}
}
}
The LINQ Aggregate call in the final method is the key. It takes three parameters:
- An initial value for the aggregation process. In our case, that's a StringBuilder.
- A Func that takes the aggregate so far and the next item to add, and returns the new aggregate. Here, we append item, a comma and a space to the StringBuilder.
- Another Func that lets you come up with the return value based on the final aggregate. In our method, we post-process the final StringBuilder with two regular expressions. The inner one removes the final comma-space. The outer one removes the second-to-last one, if it exists.
There are some limitations.
- I didn't do anything special if an item already contains a comma.
- Following typical American usage, I replaced the final comma with the word and. To many people, the Oxford Comma convention makes more sense.
- I'm sure someone could come up with one Regex that does the work of my two, but I didn't want to get carried away.
I hope you enjoyed seeing how much you can accomplish with the relatively obscure Aggregate method of LINQ.