LINQ Distinctオペレーター、大文字小文字を無視しますか?


95

次の簡単な例を考えてみましょう:

    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 にはlistと同じ数の項目が含まれています。代わりに、たとえば「3」と「3」は等しいと見なされます。

何か不足していますか、それともDistinctオペレーターの問題ですか?

回答:


229

StringComparer あなたが必要なことをします:

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

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

(または比較しているデータに応じて不変/序数/など)


5

[最も簡潔なアプローチが必要な場合は、Marc Gravellsの回答を参照してください]

いくつかの調査とBradley Graingerからの良いフィードバックの後、次の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
}

6
あなたは単にこれを必要としません。私の返事を見てください。
Marc Gravell

2
はい、「Post Your Answer」をクリックしたときと同じように返信が届きました。
アッシュ

彼らは確かに互いに20秒未満であった、と私は思い出します。それでも、IEqualityComparer <T>のようなものを実装することは、それがどのように機能するかを理解するためにさえ、まだ有用な練習です...
Marc Gravell

もう一度感謝します。誰かが強く反対しない限り、この回答をその場で公開します。
Ash

GetHashCodeはI(U + 0049)とı(U + 0131)の異なる値を報告するのに対し、Equalsはそれらを等しいと見なすため、このサンプルは、tr-TRカルチャ用に初期化すると失敗します。
Bradley Grainger

1

 ## 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は

   USA 
   INDIA
   UK

3
説明なしでコードスニペットを投稿しないでください。回答を編集して、本文を追加します。ありがとう。
クライスターズ2017

0

これははるかに単純なバージョンです。

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();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.