2009-03-05 4 views
16

Я ищу эквивалент LINQ к списку в компании Sybase() или GROUP_CONCAT в MySQL()Используйте LINQ для объединения нескольких строк в одну строку (CSV свойства)

Это будет конвертировать:

User Hobby 
-------------- 
Bob Football 
Bob Golf 
Bob Tennis 
Sue Sleeping 
Sue Drinking 

До:

User Hobby 
-------------- 
Bob Football, Golf, Tennis 
Sue Sleeping, Drinking 

ответ

17

Это оператор GroupBy. Используете ли вы LINQ для объектов?

Вот пример:

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); 
      } 
     } 
    } 
} 

Это делает группировку - вы можете управлять самостоятельно отдохнуть?

+2

Это также можно заменить внутреннюю петлю с 'string.join («», group.ToArray())', при условии, что число элементов не очень велика. –

+0

Спасибо! Я собираюсь узнать LINQ самостоятельно, а не постоянно подслушивать вас ;-) –

+8

Я единственный, кто заметил, что человек занимается спортом, в то время как увлечения женщины спят и пьют? Ты ужасный Джон Скит! – Carter

5

Смотрите, если это решение поможет вам:

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); 
    } 
} 
4

повторно в _concat аспекте вашего вопроса, используя:

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()); 
    } 
} 

выведени Еогеасп в Брюно Конде и ответы Джон Скит может стать:

Console.WriteLine("User:\tHobbies"); 
foreach (var group in groupedUsers) 
    Console.WriteLine("{0}:\t{1}", group.Key, group.Select(g => g.Hobby).AsJoined(", ")); 

... и вы получите точный формат вывода результата, который вы задали для r (да, я знаю, что другие уже решили вашу проблему, но ее трудно устоять!)

+0

это похоже на функцию MySQL GROUP_CONCAT. полезно. –

+0

@Moshe LI догадаться, что в эти дни я мог бы заменить 'group.Select (g => g.Hobby) .AsJoined (", ")' с 'String.Join (", ", from g in group select g.Hobby)' (Это требует перегрузки 'String.Join', который принимает' IEnumerable ', который был введен в .NET 4.0) –

+0

или просто использовать на 3.5' ​​group.Select (g => g.Hobby) .ToArray() '. –

2

Чтобы сделать это в одном заявлении Linq. Я бы не рекомендовал код, но он показывает, что это можно сделать.

  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)); 
     } 
3

Или же мы можем сделать включено следующее:

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 userList = users.ToList(); 
       var ug = (from user in users 
          group user by user.User into groupedUserList 
          select new { user = groupedUserList.Key, hobby = groupedUserList.Select(g =>g.Hobby)}); 

       var ug2 = (from groupeduser in ug 
          select new{ groupeduser.user, hobby =string.Join(",", groupeduser.hobby)}); 
-1

все ответы не достаточно хорошо;

потому что это db-запрос, но все мы делаем это только в памяти;

различие заключается в том, что некоторая операция в памяти будет зависеть от ошибки, не может передать значение для хранения выражения;

var list = db.Users.GroupBy(s=>s.User). 
      select(g=>new{user=g.Key,hobbys=g.select(s=>s.Hobby)}); // you can just do that from db 

var result=list.ToList(); // this is important,to query data to memory; 

var result2 = result.select(g=>new{user=g.Key,hobbyes=string.join(",",g.hobbyes)}; //then,do what you love in memory