Оператор LINQ Distinct, игнорировать случай?
учитывая следующий простой пример:
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();
похоже, что CaseInsensitiveComparer фактически не используется для сравнения без учета регистра.
другими словами distinctList содержит то же количество элементов, что и список. Вместо этого я ожидал бы, например, что "три" и "три" будут считаться равными.
Я что-то упустил или это проблема с отдельным оператором?
4 ответов:
StringComparerчто нужно:List<string> list = new List<string>() { "One", "Two", "Three", "three", "Four", "Five" }; var distinctList = list.Distinct( StringComparer.CurrentCultureIgnoreCase).ToList();(или инвариантный / порядковый / etc в зависимости от данных, которые вы сравниваете)
[см. ответ Марка Гравелса, если вы хотите самый краткий подход]
после некоторого исследования и хорошей обратной связи от Брэдли Грейнджера я реализовал следующий IEqualityComparer. Он поддерживает нечувствительный к регистру оператор Distinct () (просто передайте экземпляр этого оператору Distinct) :
class IgnoreCaseComparer : IEqualityComparer<string> { public CaseInsensitiveComparer myComparer; public IgnoreCaseComparer() { myComparer = CaseInsensitiveComparer.DefaultInvariant; } public IgnoreCaseComparer(CultureInfo myCulture) { myComparer = new CaseInsensitiveComparer(myCulture); } #region IEqualityComparer<string> 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 }
вот гораздо более простая версия.
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();
## 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); }выход будет
USA INDIA UK
Comments