Another Linqification question
Say I have a List of objects, and the object has a string property. I want to get a single comma-separated list of the value of each string property of each object in the list. Here's 1 way to do it (sans linq)
StringBuilder result = new StringBuilder()
foreach(myObject obj in myList)
{
result.Append(obj.TheString);
result.Append(", ");
}
// then trim the trailing ", " and call ToString() on result, etc, etc...
Here's my first shot at linqification. Is there a better way?
string result = string.Join(", ", myList.Select(myObj => myObj.TheString).ToArray());
That's one line of code, but it doesn't look very efficient to me -- iterate the list just to build 开发者_如何学运维an array, just to iterate the array and build a string... whew!
Is there a better way?
If you want efficient, use Enumerable.Aggregate
with StringBuilder
:
string result = myList.Aggregate(new StringBuilder(),
(sb, o) => sb.Append(o.TheString).Append(", "))
.ToString();
The original problem is that String.Join
wants an array. In .NET 4, there will be an overload that takes IEnumerable<string>
(and I expect it will be implemented like above).
I like this extension method for joining strings. It's basically the same technique you are using, but wrapped in an extension method. I wouldn't recommend it for large sets since efficiency was not the goal. The benefit to me is expressiveness (very linqy) and convenient for small sets:
[Test]
public void Should_make_comma_delimited_list()
{
var colors = new List<HasColor>
{
new HasColor { Color = "red" },
new HasColor { Color = "green" },
new HasColor { Color = "blue" }
};
var result = colors.Implode(x => x.Color, ", ");
Assert.That(result, Is.EqualTo("red, green, blue"));
}
public class HasColor
{
public string Color { get; set; }
}
public static class LinqExtensions
{
public static string Implode<T>(this IEnumerable<T> list, Func<T, string> func, string separator)
{
return string.Join(separator, list.Select(func).ToArray());
}
}
Use string.Join, it's good enough.
Optimize when profiler will tell you to do so.
Readability of the version with StringBuilder is poor and you are still getting your trailing comma.
Here's another way (result
is a StringBuilder
):
myList.ForEach(
myObj =>
{
if (result.Length != 0)
result.Append(",");
result.Append(myObj.TheString);
}
);
精彩评论