Как динамически сгруппировать список и выбрать значения, используя запрос linq в C#? - PullRequest
0 голосов
/ 25 марта 2020

У меня есть список ввода test

class Tracker
{
    public string Toolid {get;set;}
    public string Description {get;set;}
    public int length {get;set;}
    public int breadth {get;set;}
    public int height {get;set;}

}

List<Tracker> test = new List<Tracker>();
test.Add( new Tracker {Toolid="A.1",Description ="ABC",length = 10, breadth =10,height = 50});
test.Add( new Tracker {Toolid="A.1",Description ="ABC", length = 10, breadth =10,height = 50});
test.Add( new Tracker {Toolid="C.1",Description ="ABCD", length = 10, breadth =10,height = 50});
test.Add( new Tracker {Toolid="D.1",Description ="Admin123", length = 10, breadth =10,height = 50});

Этот список содержит больше значений, таких как weight, color et c. Для лучшего понимания я добавил только 5 переменных-членов в класс Tracker .

Мне нужно сгруппировать список test на основе значений другого списка ( grpList ). Этот список ( grpList ) является динамическим c, поэтому число параметров и значений в списке может измениться. Так что мне нужна динамическая c Group By списка с использованием запроса LINQ.

case 1: иногда этот список grpList содержит 2 значения.

List <string> grpList = new List<string>();

grpList.Add(ToolId);
grpList.Add(Description);

Если это так, мне нужно сгруппировать список test с ToolId и описанием,

case 2: если список grpList содержит N значений, мне нужно сгруппируйте список test со значениями 'N'.

Количество значений в grpList варьируется. У меня есть группа основной список test , используя значения в grpList. Если grpList содержит 2 значения, сгруппируйте список test с 2 значениями. если grpList содержит 5 значений, сгруппируйте список test с 5 значениями.

Примечание: мне нужно сгруппировать список test (Main список).
grpList значения только для группировки.

Ответы [ 2 ]

0 голосов
/ 28 марта 2020

Я использовал предикат селектора метода Enumerable.GroupBy. Вот как я сгенерировал предикат, и решение, кажется, работает.

public class Tracker
    {
        public string Toolid { get; set; }
        public string Description { get; set; }
        public int length { get; set; }
        public int breadth { get; set; }
        public int height { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            List<Tracker> test = new List<Tracker>();
            test.Add(new Tracker { Toolid = "A.1", Description = "ABC", length = 50, breadth = 10, height = 50 });
            test.Add(new Tracker { Toolid = "A.1", Description = "ABC", length = 20, breadth = 10, height = 50 });
            test.Add(new Tracker { Toolid = "C.1", Description = "LMN", length = 10, breadth = 10, height = 50 });
            test.Add(new Tracker { Toolid = "D.1", Description = "Admin123", length = 7, breadth = 10, height = 50 });

            List<string> grpList = new List<string>();
            grpList.Add("length");
            grpList.Add("Description");

            var sourceParm = Expression.Parameter(typeof(Tracker), "x");
            List<Expression> propertyExpressions = new List<Expression>();
            foreach (var f in grpList.ToArray())
            {
                Expression conv = Expression.Convert(Expression.Property(sourceParm, f), typeof(object));
                propertyExpressions.Add(conv);
            }

            var concatMethod = typeof(string).GetMethod(
                                                   "Concat",
                                                    new[] { typeof(object), typeof(object), typeof(object) });
            Expression body = propertyExpressions.Aggregate((x, y) => Expression.Call(concatMethod, 
                                                                            x,
                                                                            Expression.Constant(","), 
                                                                            y));
            var groupSelector = Expression.Lambda<Func<Tracker, string>>(body, sourceParm);
            var j = test.GroupBy(groupSelector.Compile());
}
0 голосов
/ 25 марта 2020

попробуйте отражение:

List<string> grpList = new List<string>();
grpList.Add("Toolid");
grpList.Add("Description");

var groups = new Dictionary<string, IEnumerable>();
var all_properties = typeof(Tracker).GetProperties();

foreach ( var prop_name in grpList )
{
    var prop = all_properties.First( x => x.Name == prop_name);
    var group = test.GroupBy( x =>  prop.GetValue( x ) );
    groups.Add( prop_name, group );
}

, если вы хотите иметь вложенную группировку, подобную sql, примените GroupBy к результирующим группам:

var groups = new List<List<Tracker>>() { test };
foreach ( var prop_name in grpList )
{
    var prop = all_properties.First( x => x.Name == prop_name);
    var newgroups = new List<List<Tracker>>();
    foreach ( var group in groups)
    {
        var subgroups = group.GroupBy( x => prop.GetValue( x ) );                   
        newgroups.AddRange( subgroups.Select(g => g.ToList()).ToList() );                                       
    }
    groups = newgroups;
}
...