استخدم LINQ لتسلسل صفوف متعددة في صف واحد (خاصية CSV)
-
03-07-2019 - |
سؤال
أنا أبحث عن LINQ المكافئ لـ Sybase's LIST() أو group_concat() في MySQL
سيتم تحويل:
User Hobby
--------------
Bob Football
Bob Golf
Bob Tennis
Sue Sleeping
Sue Drinking
ل:
User Hobby
--------------
Bob Football, Golf, Tennis
Sue Sleeping, Drinking
المحلول
وهذا هو المشغل 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);
}
}
}
}
وهذا لا تجمع - يمكنك إدارة ما تبقى نفسك
نصائح أخرى
ونرى ما اذا كان هذا الحل يساعدك على:
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);
}
}
وإعادة الجانب _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() );
}
}
ووforeach إخراج في كوندي برونو والأجوبة جون السكيت يمكن أن تصبح:
Console.WriteLine( "User:\tHobbies");
foreach ( var group in groupedUsers )
Console.WriteLine( "{0}:\t{1}", group.Key, group.Select( g => g.Hobby ).AsJoined( ", " ) );
... وستحصل على شكل الناتج نتيجة الدقيق الذي طلب (نعم، وأنا أعلم أن البعض الآخر قد حل بالفعل مشكلتك، ولكن من الصعب أن تقاوم!)
وإلا فإننا يمكن أن تفعل following-
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)});
لتفعل ذلك في بيان ينق واحد. لا توجد وسيلة أنصح الرمز، لكنه يظهر أنه يمكن القيام به.
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));
}
كل الإجابات ليست جيدة بما فيه الكفاية؛
لأن هذا استعلام قاعدة بيانات، لكننا جميعًا نفعل ذلك في الذاكرة فقط؛
الفرق هو أن بعض العمليات في الذاكرة ستحدث خطأ لا يمكن نقله لتخزين التعبير؛
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