简体   繁体   中英

Linq group by multiple columns with anonymous column

I do not know how to correctly word the question but I have :

            var groups = data.GroupBy(x => new {x.EntityId, x.StartLocal = new {
                var stamp = x.StartLocal;
                stamp = stamp.AddHours(-(stamp.Hour % hours));
                stamp = stamp.AddMinutes(-stamp.Minute);
                stamp = stamp.AddMilliseconds(-stamp.Millisecond);
                return stamp;
            }})
.Select(...)
            .ToList();

which doesnt work (bad syntax). I would first like to group by the entityId then by the hour of a field called StartLocal , like if I was to group the results by every 2 hours I would get :

Id = 1
     Hour = 2
     Hour = 4
Id = 2
     Hour = 2
...

like so.

What I need to fill :

        DO obj = new DO
        {
            EntityId = pp.EntityId,
            EntityCode = pp.EntityCode,
            StartLocal = pp.StartLocal,
            Volume = pp.Volume,
        };

The Volume is what needs to be aggregated. So basically 1000's of these DO's come as an array then they are split by the EntityId, and then by the hours of StartLocal ... the volume is aggregated for x amount of hours worth, and the same DO's created ... but now much less of them.

It seems like you want something like this:

var groups = data.GroupBy(x => 
    {
        var stamp = x.StartLocal;
        stamp = stamp.AddHours(-(stamp.Hour % hours));
        stamp = stamp.AddMinutes(-stamp.Minute);
        stamp = stamp.AddMilliseconds(-stamp.Millisecond);
        return new { x.EntityId, StartLocal = stamp };
    });

Or more simply:

var groups = data.GroupBy(x => new 
    { 
        x.EntityId, 
        StartLocal = new DateTime(
            x.StartLocal.Year, 
            x.StartLocal.Month, 
            x.StartLocal.Day, 
            x.StartLocal.Hour % hours, 0, 0)
    });

Both of these give StartLocal rounded down to an hour. If you want just the hour by itself, you can do this:

var groups = data.GroupBy(x => new { x.EntityId, x.StartLocal.Hour % hours });

You should explain why you're trying to do at a higher level. There may be other (better) ways to accomplish what you're trying to do.

Judging by what you're doing, it looks to me like you're just trying to group items by their id and the date and hour it started. You don't need to try to create a single DateTime object to represent the date and hour as you're trying to do, just get the components separately. And besides, chances are your query provider doesn't support complex selectors, this doesn't look like a LINQ to objects query.

Just do this:

var groups = data.GroupBy(x => new
    {
        x.EntityId,
        StartDate = x.StartLocal.Date,
        StartHour = x.StartLocal.Hour,
    })
    .Select(...)
    .ToList();

What you really need here is to calls to GroupBy , rather than a single call grouping on a complex object.

var query = data.GroupBy(item => item.EntityId)
    .Select(group => group.GroupBy(item => item.StartLocal));

This will give you your tree of depth 3 instead of two, or groups of groups in other words.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM