Bazïnga
Bazïnga

Reputation: 51

Group and Merge multiple values from single List using LINQ

I have the following enums and class

internal enum flag_dead_alive
{
    none = 0
    ,
    dead = 1
    ,
    alive = 2
}

internal enum flag_blocked_unblocked
{
    none = 0
    ,
    blocked = 1
    ,
    unblocked = 2
}

internal class cls_entry
{
    internal string id_number { get; set; }

    internal flag_dead_alive dead_alive { get; set; }

    internal flag_blocked_unblocked blocked_unblocked { get; set; }
}

I have List which contains hundreds of thousands of records, so for testing purposes I have created a sample list that contain the same sort of records, below (id_number is deliberately set as string for reasons that are irrelevant right now)

List<cls_npr_entry> output = new List<cls_npr_entry>()
            {
                new cls_npr_entry() { id_number = "1", dead_alive = flag_dead_alive.alive, blocked_unblocked = flag_blocked_unblocked.none }
                ,
                new cls_npr_entry() { id_number= "1", dead_alive = flag_dead_alive.none, blocked_unblocked= flag_blocked_unblocked.blocked }
                ,
                new cls_npr_entry(){id_number= "2", dead_alive = flag_dead_alive.none, blocked_unblocked= flag_blocked_unblocked.blocked }
                ,
                new cls_npr_entry(){id_number= "3", dead_alive = flag_dead_alive.dead, blocked_unblocked= flag_blocked_unblocked.none }
                ,
                new cls_npr_entry(){id_number= "3", dead_alive = flag_dead_alive.none, blocked_unblocked= flag_blocked_unblocked.unblocked }
            };

From the list, I want to get output of grouped and merged (is that the correct term here?) records from my list. However, any enum that is set to "none" should be discarded if a matched record has a different value to "none", otherwise it must remain "none". For example, the output for the above list should be

1 : id_number = 1, dead_alive = alive, blocked_unblocked = blocked
2 : id_number = 2, dead_alive = none, blocked_unblocked = blocked
3 : id_number = 3, dead_alive = dead, blocked_unblocked = unblocked

The code

var groups = output.GroupBy(x => x.id_number);

returns the records in the correct groups, but I have no idea where to from here. I also have

var groups = output.GroupBy(x => x.id_number).Select(g => g.Select(y => new { y.id_number, y.blocked_unblocked, y.dead_alive }));

but that returns the same result as the first query. I need to figure out how to select one record from y.dead_alive and one record from y.blocked_unblocked, so that the result only returns only the relevant record to create one record from both.

All help would be appreciated.

Upvotes: 2

Views: 289

Answers (1)

Mohammed Sajid
Mohammed Sajid

Reputation: 4913

For your outputtest list, you can get theMax of dead_alive and blocked_unblocked after grouping, like the following code:

var groups = output.GroupBy(x => x.id_number)
    .Select(y => new cls_entry
    {
        id_number = y.Key,
        dead_alive = y.Max(e => e.dead_alive),
        blocked_unblocked = y.Max(e => e.blocked_unblocked)
    }).ToList();

Documentation of Max method : Max

Upvotes: 2

Related Questions