【问题标题】:Use LINQ to concatenate multiple rows into single row (CSV property)使用 LINQ 将多行连接成单行(CSV 属性)
【发布时间】:2010-10-11 12:02:52
【问题描述】:

我正在寻找与 Sybase 的 LIST() 或 MySQL 的 group_concat() 等效的 LINQ

它会转换:

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

收件人:

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

【问题讨论】:

    标签: linq csv group-concat linq-group


    【解决方案1】:

    所有答案都不够好;

    因为这是一个数据库查询,但我们所有人都只是在内存中这样做;

    区别是内存中的某些操作会发生错误can't trans to store expression;

    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
    

    【讨论】:

      【解决方案2】:

      否则我们可以执行以下操作-

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

      【讨论】:

        【解决方案3】:

        在一个 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));
                }
        

        【讨论】:

          【解决方案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() );
              }
          }
          

          bruno conde 和 Jon Skeet 的答案中的输出 foreach 可以变成:

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

          ...你会得到你要求的精确结果输出格式(是的,我知道其他人已经解决了你的问题,但很难抗拒!)

          【讨论】:

          • 这就像 MySQL 的 GROUP_CONCAT 函数。有用。
          • @Moshe LI 猜想这些天我可能会用String.Join(",", from g in group select g.Hobby) 替换group.Select( g =&gt; g.Hobby ).AsJoined( ", " )(这需要String.Join 的重载,它需要IEnumerable&lt;T&gt;,这是在.NET 4.0 中引入的)
          • 或仅在 3.5 group.Select( g =&gt; g.Hobby ).ToArray() 上使用。
          【解决方案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);
              }
          }
          

          【讨论】:

            【解决方案6】:

            这就是 GroupBy 运算符。你在使用 LINQ to Objects 吗?

            这是一个例子:

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

            这样分组 - 你能自己管理其余的吗?

            【讨论】:

            • 也可以用String.Join(", ", group.ToArray())代替内层循环,只要元素个数不是很大。
            • 谢谢!我要自己学习 LINQ,而不是不断地打扰你 ;-)
            • 我是唯一一个注意到男人喜欢运动而女人的爱好是睡觉和喝酒的人吗?你是可怕的乔恩·斯基特!
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-02-25
            • 1970-01-01
            • 1970-01-01
            • 2014-06-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多