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?

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)


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
}

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

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();
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.