Составить LINQ запрос
От: _NN_ www.nemerleweb.com
Дата: 03.09.15 18:40
Оценка: 5 (1)
Сейчас код написан немного итеративно, но хочется как-нибудь его улучшить.

Задача сгруппировать по полю Name при этом все значения создаются с одним и тем же экземпляром (используется первый).
Также мне нужно суммировать все X и Y в этих группах.

Есть идеи получше ?
Заранее спасибо.

using System;
using System.Collections.Generic;
using System.Linq;

class Outer
{
    public int A;
}

class WithName
{
    public string Name;
}

class Id
{
    public int I;
}

class State
{
    public int X;
    public int Y;
}


class ResultWithName
{
    public int SumX;
    public int SumY;
    public readonly WithName WithName;

    public ResultWithName(WithName withName)
    {
        WithName = withName;
    }
}

public class Program
{
    public static void Main()
    {
        var values = TestValues();

        var result = new Dictionary<Outer, Dictionary<string, ResultWithName>>();
        foreach (var kv in values)
        {
            var innerValues = kv.Value;

            Dictionary<string, ResultWithName> nameGroup;
            if (!result.TryGetValue(kv.Key, out nameGroup))
            {
                nameGroup = result[kv.Key] = new Dictionary<string, ResultWithName>();
            }

            foreach (var innerKv in innerValues.GroupBy(p => p.Key.Name))
            {
                var withName = (WithName)null;

                foreach (var state in 
                    from w in innerKv
                    from idStates in w.Value
                    from state in idStates.Value
                    select state)
                {
                    // Use first name
                    if (withName == null) withName = innerKv.First().Key;

                    var localWithName = withName;
                    ResultWithName resultWithName;
                    if (!nameGroup.TryGetValue(innerKv.Key, out resultWithName))
                    {
                        resultWithName = nameGroup[innerKv.Key] = new ResultWithName(localWithName);
                    }

                    resultWithName.SumX += state.X;
                    resultWithName.SumY += state.Y;
                }
            }
        }


        Console.ReadKey();
    }

    private static Dictionary<Outer, Dictionary<WithName, Dictionary<Id, List<State>>>> TestValues()
    {
        return new Dictionary<Outer, Dictionary<WithName, Dictionary<Id, List<State>>>>
        {
            {
                new Outer {A = 1},
                new Dictionary<WithName, Dictionary<Id, List<State>>>
                {
                    {
                        new WithName {Name = "2"},
                        new Dictionary<Id, List<State>>
                        {
                            {
                                new Id {I = 3},
                                new List<State>
                                {
                                    new State {X = 1, Y = 2},
                                    new State {X = 3, Y = 4},
                                    new State {X = 5, Y = 6},
                                }
                            },
                            {
                                new Id {I = 4},
                                new List<State>
                                {
                                    new State {X = 11, Y = 22},
                                    new State {X = 31, Y = 24},
                                    new State {X = 51, Y = 26},
                                }
                            },
                        }
                    },
                    {
                        new WithName {Name = "20"},
                        new Dictionary<Id, List<State>>
                        {
                            {
                                new Id {I = 3},
                                new List<State>
                                {
                                    new State {X = 6, Y = 1},
                                    new State {X = 7, Y = 3},
                                    new State {X = 8, Y = 9},
                                }
                            },
                            {
                                new Id {I = 4},
                                new List<State>
                                {
                                    new State {X = 11, Y = 22},
                                    new State {X = 31, Y = 24},
                                    new State {X = 51, Y = 26},
                                }
                            },
                        }
                    },
                }
            }
        };
    }
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Отредактировано 07.09.2015 17:58 _NN_ . Предыдущая версия .
Re: Составить LINQ запрос
От: codenet Россия  
Дата: 10.09.15 19:23
Оценка: 53 (3)
Здравствуйте, _NN_, Вы писали:

далеко не претендует на хороший вариант,но если немного поправишь под себя
может получишь поаккуратнее

 var res = from x in innerValues
                    group x by x.Key.Name
                    into gr
                    from y in gr
                    from q in y.Value
                    let f = gr.First()
                              select new { key = gr.Key, first = f, X = q.Value.Sum(s => s.X), Y = q.Value.Sum(s => s.Y) }
                    into tmp
                    group tmp by tmp.key 
                    into ww
                    select new { firstObj = ww.First().first, sumX = ww.Sum(s => s.X), sumY = ww.Sum(s => s.Y) };

да можно было подумать и написать лучше ,но это первое что в голову стукнуло
Re[2]: Составить LINQ запрос
От: _NN_ www.nemerleweb.com
Дата: 11.09.15 11:04
Оценка:
Здравствуйте, codenet, Вы писали:

C>да можно было подумать и написать лучше ,но это первое что в голову стукнуло

Боюсь переписывать уже не буду, сейчас работает и этого достаточно.
Только если логику придется менять.
Если есть желание и возможность буду рад если получится упростить код.
http://rsdn.nemerleweb.com
http://nemerleweb.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.