LINQ Operator berbeda, abaikan kasus?

96

Diberikan contoh sederhana berikut:

    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();

Tampaknya CaseInsensitiveComparer sebenarnya tidak digunakan untuk melakukan perbandingan tidak peka huruf besar / kecil.

Dengan kata lain differentList berisi jumlah item yang sama dengan list . Sebaliknya, saya berharap, misalnya, "Tiga" dan "tiga" dianggap sama.

Apakah saya melewatkan sesuatu atau apakah ini masalah dengan operator Berbeda?

Abu
sumber

Jawaban:

233

StringComparer melakukan apa yang Anda butuhkan:

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

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

(atau invarian / ordinal / etc tergantung pada data yang Anda bandingkan)

Marc Gravell
sumber
5

[Lihat jawaban Marc Gravells jika Anda menginginkan pendekatan yang paling ringkas]

Setelah beberapa penyelidikan dan umpan balik yang baik dari Bradley Grainger, saya telah menerapkan IEqualityComparer berikut. Ini mendukung pernyataan Distinct () yang tidak peka huruf besar / kecil (cukup teruskan contoh ini ke operator 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
}
Abu
sumber
6
Anda tidak membutuhkan ini. Lihat balasan saya.
Marc Gravell
2
Ya, balasan Anda tiba tepat ketika saya mengklik "Posting Jawaban Anda".
Abu
Mereka pasti dengan <20 detik satu sama lain, saya ingat. Namun, menerapkan sesuatu seperti IEqualityComparer <T> masih merupakan latihan yang berguna, jika hanya untuk memahami cara kerjanya ...
Marc Gravell
Terima kasih sekali lagi, saya akan membiarkan jawaban ini hidup, kecuali ada yang keberatan.
Abu
Sampel ini gagal saat diinisialisasi untuk budaya tr-TR jika budaya saat ini adalah en-US, karena GetHashCode akan melaporkan nilai yang berbeda untuk I (U + 0049) dan ı (U + 0131), sedangkan Equals akan menganggapnya sama.
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 akan menjadi

   USA 
   INDIA
   UK
Javed Ahmad
sumber
3
Harap hindari memposting cuplikan kode tanpa penjelasan. Edit jawaban Anda dan tambahkan isi padanya. Terima kasih.
Clijsters
0

Ini adalah versi yang jauh lebih sederhana.

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();
Brandon
sumber