LINQ Distinct operator, ignore case?

C#LinqStringComparisonDistinct

C# Problem Overview


Given the following simple example:

    List<string> list = new List<string>() { "One", "Two", "Three", "three", "Four", "Five" };

    CaseInsensitiveComparer ignoreCaseComparer = new CaseInsensitiveComparer();

    var distinctList = list.Distinct(ignoreCaseComparer as IEqualityComparer<string>).ToList();

It appears the CaseInsensitiveComparer is not actually being used to do a case-insensitive comparison.

In other words distinctList contains the same number of items as list. Instead I would expect, for example, "Three" and "three" be considered equal.

Am I missing something or is this an issue with the Distinct operator?

C# Solutions


Solution 1 - C#

StringComparer does what you need:

List<string> list = new List<string>() {
    "One", "Two", "Three", "three", "Four", "Five" };

var distinctList = list.Distinct(
    StringComparer.CurrentCultureIgnoreCase).ToList();

(or invariant / ordinal / etc depending on the data you are comparing)

Solution 2 - C#

[See Marc Gravells answer if you want the most concise approach]

After some investigation and good feedback from Bradley Grainger I've implemented the following IEqualityComparer. It suports a case insensitive Distinct() statement (just pass an instance of this to the Distinct operator) :

> class IgnoreCaseComparer : IEqualityComparer > { > public CaseInsensitiveComparer myComparer; > > public IgnoreCaseComparer() > { > myComparer = CaseInsensitiveComparer.DefaultInvariant; > } > > public IgnoreCaseComparer(CultureInfo myCulture) > { > myComparer = new CaseInsensitiveComparer(myCulture); > } > > #region IEqualityComparer Members > > public bool Equals(string x, string y) > { > if (myComparer.Compare(x, y) == 0) > { > return true; > } > else > { > return false; > } > } > > public int GetHashCode(string obj) > { > return obj.ToLower().GetHashCode(); > } > > #endregion > }

Solution 3 - C#


 ## Distinct Operator( Ignoring Case) ##
  string[] countries = {"USA","usa","INDIA","UK","UK" };

  var result = countries.Distinct(StringComparer.OrdinalIgnoreCase);

  foreach (var v in result) 
  { 
  Console.WriteLine(v);
  }

OutPut will Be

   USA 
   INDIA
   UK

Solution 4 - C#

Here is a far simpler version.

List<string> list = new List<string>() { "One", "Two", "Three", "three", "Four", "Five" };

var z = (from x in list select new { item = x.ToLower()}).Distinct();

z.Dump();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAshView Question on Stackoverflow
Solution 1 - C#Marc GravellView Answer on Stackoverflow
Solution 2 - C#AshView Answer on Stackoverflow
Solution 3 - C#Javed AhmadView Answer on Stackoverflow
Solution 4 - C#MorrisonView Answer on Stackoverflow