LINQ groupby отсортировать в группе

159
03 января 2022, 08:30

Нужно сгруппировать все паллеты по сроку годности, отсортировать по возрастанию срока годности, в каждой группе отсортировать паллеты по весу.

class Pallete
{
    public List<Box> boxes { get; private set; }
    public DateTime? getExpirationDate() {
        return boxes.Min(b => b.ExpirationDate);
    }
    public int getWeight() {
        return boxes.Sum(b => b.Weight) + 30;
    }
}

Получилось сгруппировать все паллеты по сроку годности, отсортировать по возрастанию срока годности. Как теперь в каждой группе отсортировать по весу?

private List<Pallete> palletes;
    public void getGroupedBy() {
        var g = palletes
            .GroupBy(p => p.getExpirationDate())
            .OrderBy(p => p.Key);
        foreach (var x in g)
        {
            System.Console.WriteLine("ExDate:{0}", x.Key);
            foreach (var y in x)
            {
                System.Console.WriteLine("=====weight:{0}, id:{1}", y.getWeight(), y.Id);
            }
        }
    }

UPDATE Сделал так

    public void getGroupedBy() {
        var g = palletes
            .GroupBy(p => p.getExpirationDate())
            .OrderBy(p => p.Key)
            .ToDictionary(p => p.Key, p => p.OrderBy(p => p.getWeight()))
            .GroupBy(p => p.Key);
        foreach (var x in g)
        {
            System.Console.WriteLine("ExDate:{0}", x.Key);
            foreach (var y in x)
            {
                System.Console.WriteLine("==ExDate:{0}", y.Key);
                foreach (var z in y.Value) {
                    System.Console.WriteLine("=====weight:{0}, id:{1}", z.getWeight(), z.Id);
                }
            }
        }
    }

На мой взгляд кривовато. Можно как то улучшить результирующую структуру? Привести к IGrouping?

Answer 1

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

var g = palletes
    .GroupBy(p => p.getExpirationDate())
    .Select(x => new { x.Key, Items = x.OrderBy(z=>z.getExpirationDate()).ToArray() })
    .OrderBy(p => p.Key).ToArray();
foreach (var x in g)
{
    System.Console.WriteLine("ExDate:{0}", x.Key);
    foreach (var y in x.Items)
    {
        System.Console.WriteLine("=====weight:{0}, id:{1}", y.getWeight(), y.Id);
    }
}

Если надо обернуть в функцию

public Tuple<DateTime?, Pallete[]>[] Foo()
{
    var g = palletes
    .GroupBy(p => p.getExpirationDate())
    .Select(x => Tuple.Create(x.Key, x.OrderBy(z => z.getExpirationDate()).ToArray()))
    .OrderBy(p => p.Item1).ToArray();
    foreach (var x in g)
    {
        System.Console.WriteLine("ExDate:{0}", x.Item1);
        foreach (var y in x.Item2)
        {
            System.Console.WriteLine("=====weight:{0}, id:{1}", y.getWeight(), y.Id);
        }
    }       
    return g;
}
READ ALSO
Что отвечает за анимацию Item в Terraria?

Что отвечает за анимацию Item в Terraria?

создал новый предмет и в SetDefaults закинул строчку:

149
Обратный метод к Camera.ScreenToWorldPoint()

Обратный метод к Camera.ScreenToWorldPoint()

В движок Unity встроен метод ScreenToWorldPoint(), который координаты точки на экране конвертирует в координаты соответствующей точки на карте(сцене/мире)Есть...

99
Поиск папок в C#

Поиск папок в C#

КАК через Stack написать код поиска папок на компютере?

84
Почему не получается передать в обобщенный метод коллекцию типов, реализующих интерфейс, без установки ограничений на &lt;T&gt;

Почему не получается передать в обобщенный метод коллекцию типов, реализующих интерфейс, без установки ограничений на <T>

Опыт программирования небольшой, помогите, пожалуйста, разобратьсяИмеется интерфейс IPinHelper с методом PinFavoriteItem:

124