3

I have a list:

List<Dev> devices= new List<Dev>(){
    new Dev{ Add="5",Name="A" },
    new Dev{ Add="5",Name="a" },
    new Dev{ Add="9",Name="b" },
    new Dev{ Add="6",Name="c" },
    new Dev{ Add="9",Name="b" },

};

I want to write a Linq "Lambda Expression" which return the records that are not duplicates and also the first record from duplicates based on "Name" in the list. Also ignore case while finding duplicates

Expected Output:

Add=5, Name=A
Add=9, Name=b
Add=6, Name=c

Query what I have now (It returns the "Name" which is duplicate):

results.GroupBy(x => x.Name, StringComparer.OrdinalIgnoreCase)
                                  .Where(g => g.Count() > 1)
                                  .Select(g => g.Key)
                                  .ToList();    
Dot Net Dev
  • 454
  • 5
  • 17

1 Answers1

4

You are pretty close: rather than picking g.Key, pick g.First(), and remove filtering by count:

var list = results.GroupBy(x => x.Name, StringComparer.OrdinalIgnoreCase)
                  .Select(g => g.First())
                  .ToList();
Sergey Kalinichenko
  • 675,664
  • 71
  • 998
  • 1,399
  • Is it specified that Enumerable.GroupBy keeps the original Order? Or could it be that in group 5 the first element is the one with the name 'a', with 'A' as second? In that cast this answer does not return the requested object – Harald Coppoolse Jan 08 '18 at 12:39
  • @HaraldCoppoolse [Yes, LINQ guarantees the order](https://stackoverflow.com/a/12377922/335858). – Sergey Kalinichenko Jan 08 '18 at 13:36
  • @dasblinkenlight I believe we can also use "x=>x.Name.ToLower()" instead of "StringComparer.OrdinalIgnoreCase". So, which one should we go with for better performance and accuracy? – Dot Net Dev Jan 08 '18 at 16:55
  • 1
    @DotNetDev `StringComparer.OrdinalIgnoreCase` looks cleaner, because it avoids creating temporary `string` objects that are used for grouping, and then promptly discarded. – Sergey Kalinichenko Jan 08 '18 at 16:56