I'm looking for the LINQ equivalent to the Sybase's LIST() or MySQL's group_concat()
It'll convert:
User Hobby
--------------
Bob Football
Bob Golf
Bob Tennis
Sue Sleeping
Sue Drinking
To:
User Hobby
--------------
Bob Football, Golf, Tennis
Sue Sleeping, Drinking
From stackoverflow
-
That's the GroupBy operator. Are you using LINQ to Objects?
Here's an example:
using System; using System.Collections.Generic; using System.Linq; public class Test { static void Main() { var users = new[] { new { User="Bob", Hobby="Football" }, new { User="Bob", Hobby="Golf" }, new { User="Bob", Hobby="Tennis" }, new { User="Sue", Hobby="Sleeping" }, new { User="Sue", Hobby="Drinking" }, }; var groupedUsers = users.GroupBy(user => user.User); foreach (var group in groupedUsers) { Console.WriteLine("{0}: ", group.Key); foreach (var entry in group) { Console.WriteLine(" {0}", entry.Hobby); } } } }
That does the grouping - can you manage the rest yourself?
Hosam Aly : It's also possible to replace the inner loop with `String.Join(", ", group.ToArray())`, as long as the number of elements is not very large.John Paul Jones : Thanks! I'm going to learn LINQ myself instead of constantly bugging you ;-)Carter : Am I the only one that noticed the man is into sports while the woman's hobbies are sleeping and drinking? You're terrible Jon Skeet!Jon Skeet : @Carter: They're not *my* examples...Carter : Ha, you're right, my bad. Still funny. -
See if this solution helps you:
List<User> users = new List<User>() { new User {Name = "Bob", Hobby = "Football" }, new User {Name = "Bob", Hobby = "Golf"}, new User {Name = "Bob", Hobby = "Tennis"}, new User {Name = "Sue", Hobby = "Sleeping"}, new User {Name = "Sue", Hobby = "Drinking"} }; var groupedUsers = from u in users group u by u.Name into g select new { Name = g.First<User>().Name, Hobby = g.Select(u => u.Hobby) }; foreach (var user in groupedUsers) { Console.WriteLine("Name: {0}", user.Name); foreach (var hobby in user.Hobby) { Console.WriteLine("Hobby: {0}", hobby); } }
-
re the
_concat
aspect of your question, using:static class EnumerableExtensions { public static String AsJoined( this IEnumerable<String> enumerable ) { return AsJoined( enumerable, "," ); } public static String AsJoined( this IEnumerable<String> enumerable, String separator ) { return String.Join( separator, enumerable.ToArray() ); } }
The outputting foreach in bruno conde and Jon Skeet's answers can become:
Console.WriteLine( "User:\tHobbies"); foreach ( var group in groupedUsers ) Console.WriteLine( "{0}:\t{1}", group.Key, group.Select( g => g.Hobby ).AsJoined( ", " ) );
... and you'll get the precise result output format you asked for (yes, I know the others have already solved your problem, but its hard to resist!)
-
To do it in one Linq Statement. There is no way I'd recommend the code, but it shows that it could be done.
var groupedUsers = from user in users group user by user.User into userGroup select new { User = userGroup.Key, userHobies = userGroup.Aggregate((a, b) => new { User = a.User, Hobby = (a.Hobby + ", " + b.Hobby) }).Hobby } ; foreach (var x in groupedUsers) { Debug.WriteLine(String.Format("{0} {1}", x.User, x.userHobies)); }
0 comments:
Post a Comment