Search code examples
c#linqlambda

C# linq lambda select from group not working


I have a list, I need to find out which name group doesn't have server A

var list = new[]
        {
            new { name = "object1", server="A"},
            new { name = "object1", server="B"},
            new { name = "object2", server="B"},
            new { name = "object2", server="C"},
            new { name = "object3", server="B"},
            new { name = "object3", server="A"},
            new { name = "object4", server="C"},
        };

var selectServerANotPresent = list.AsEnumerable()
            .GroupBy(g => g.name, (key, k) => k.Where(s => s.server == "A"))
            .Where(w => w.Count() == 0)
            .Select(s=>s.FirstOrDefault()) //My issue is in this line
            .ToList();

System.Diagnostics.Debug.WriteLine(string.Join("\r\n", selectServerANotPresent));

It's returning a list of 2 items with NULL entries. How do I make this print out like below?

{ name="object2", server="B" }
{ name="object4", server="C" }

Solution

  • You're currently discarding all non-server-A objects when you do the grouping. (By the time you get to the line where your comment says you think the problem is, you're looking at an empty group.)

    Instead, just group by name and make the filtering part check whether the group contains any server-A values:

    using System;
    using System.Linq;
    
    var data = new[]
    {
        new { Name = "object1", Server = "A"},
        new { Name = "object1", Server = "B"},
        new { Name = "object2", Server = "B"},
        new { Name = "object2", Server = "C"},
        new { Name = "object3", Server = "B"},
        new { Name = "object3", Server = "A"},
        new { Name = "object4", Server = "C"},
    };
    var selectServerANotPresent = data
        .GroupBy(o => o.Name)
        .Where(group => !group.Any(o => o.Server == "A"))
        .Select(group => group.First())
        .ToList();
    
    selectServerANotPresent.ForEach(Console.WriteLine);
    

    Output:

    { Name = object2, Server = B }
    { Name = object4, Server = C }