GroupBy с несколькими группами в виде иерархии - PullRequest
4 голосов
/ 08 августа 2010

Я использую GroupBy для создания иерархического набора групп для использования в нескольких дочерних сетках.

Предположим, у меня есть запрос с 6 столбцами, a, b, c, d, e, f.

Теперь мне нужно сгруппировать по a, затем по b, затем по c.и вернуть всю строку в группе с.

var q = rows.GroupBy(x => x.a)

Хорошо, это хорошо.Это дает мне мою группу.Далее мы рассмотрим их группирование по a и b.

var q1 = q.Select(g =>new {
    Key = g.Key,
    SubGroup = g.GroupBy(x => x.b)
}

Хорошо, это тоже хорошо работает.Я получаю свою группу а с подгруппами из б.

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

var q2 = q1.Select(g1 => new {
    Key = g1.Key,
    SubGroup = g1.GroupBy(x => x.c)
}

Это не компилируется.Говорит мне, что на g1 нет GroupBy.

var q2 = q.Select(g1 => new {
    Key = g1.Key,
    SubGroup = g1.GroupBy(x => x.c)
}

Это не дает мне подгруппу b, только a и c.

Любое представление о том, что я делаю неправильноздесь?

РЕДАКТИРОВАТЬ:

Следующее также не работает, говоря, что нет определения для g1.Key

var q2 = q.Select(g => new {
    Key = g.Key,
    SubGroup = g.Select(g1 => new {
            Key = g1.Key
            SubGroup = g1.GroupBy(a => a.c)
        })

Я так плохо понимаю, чтоэто делается внутри.

Ответы [ 2 ]

5 голосов
/ 08 августа 2010

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

Но если выхотите использовать GroupBy и IGroupings для управления, вы работаете над этим не с того конца.Вы хотите начать с самого глубокого уровня и продолжить.

var groups = rows
    .GroupBy(x => new { x.A, x.B, x.C, x.D, x.E, x.F })
    .GroupBy(x => new { x.Key.A, x.Key.B, x.Key.C, x.Key.D, x.Key.E })
    .GroupBy(x => new { x.Key.A, x.Key.B, x.Key.C, x.Key.D, })
    .GroupBy(x => new { x.Key.A, x.Key.B, x.Key.C })
    .GroupBy(x => new { x.Key.A, x.Key.B })
    .GroupBy(x => x.Key.A);

groups.First().Key;             // will be an A value
groups.First().First().First(); // will be an A, B, C group
2 голосов
/ 08 августа 2010

GroupBy на самом деле поддерживает предоставление списка элементов для группировки. Каждая группа будет содержать одинаковые первые 3 элемента (A, B и C). Вы можете получить ключ с помощью метода .Key и поэкспериментировать с различными строками с помощью foreach. Смотрите пример:

    var groups = Elements.GroupBy(x => new {x.A, x.B, x.C});
    foreach (var group in groups)
    {
        Trace.WriteLine(group.Key + ": " + group.Count());
        foreach (var row in group)
        {
            Trace.WriteLine(row.D);
        }
    }

Редактировать: Ааа, хорошо, тогда вам нужно:

    var groups = Elements
        .GroupBy(a => new {a.A})
        .Select(g1 => new {
            A = g1.Key, 
            Groups = g1
            .GroupBy(b=> new {b.B})
            .Select(g2 => new {
                B = g2.Key,
                Groups = g2
                .GroupBy(c => new {c.C})
                .Select(g3 => new {
                    C = g3.Key,
                    Rows = g3
                })
            })
        });

    foreach (var groupA in groups)
    {
        Trace.WriteLine(groupA.A);
        foreach (var groupB in groupA.Groups)
        {
            Trace.WriteLine("\t" + groupB.B);
            foreach (var groupC in groupB.Groups)
            {
                Trace.WriteLine("\t\t" + groupC.C);
                foreach (var row in groupC.Rows)
                {
                    Trace.WriteLine("Row: " + row.ToString());
                }
            }
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...