LINQ Toán tử riêng biệt, bỏ qua trường hợp?


95

Cho ví dụ đơn giản sau:

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

Có vẻ như CaseInsensitiveComparer không thực sự được sử dụng để so sánh không phân biệt chữ hoa chữ thường.

Nói cách khác, danh sách riêng biệt chứa cùng một số mục như danh sách . Thay vào đó, tôi mong đợi, ví dụ: "Ba" và "ba" được coi là bằng nhau.

Tôi có thiếu thứ gì đó không hay đây là vấn đề với nhà điều hành Distinction?

Câu trả lời:


229

StringComparer hiện những gì bạn cần:

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

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

(hoặc bất biến / thứ tự / v.v. tùy thuộc vào dữ liệu bạn đang so sánh)


5

[Xem câu trả lời của Marc Gravells nếu bạn muốn cách tiếp cận ngắn gọn nhất]

Sau một số điều tra và phản hồi tốt từ Bradley Grainger, tôi đã triển khai IEqualityComparer sau đây. Nó cung cấp câu lệnh Distinction () không phân biệt chữ hoa chữ thường (chỉ cần chuyển một trường hợp của câu lệnh này tới toán tử Distinction):

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
Đơn giản là bạn không cần cái này. Xem trả lời của tôi.
Marc Gravell

2
Có, câu trả lời của bạn đã đến ngay khi tôi nhấp vào "Đăng câu trả lời của bạn".
Ash

Tôi nhớ lại chắc chắn họ đã ở với nhau <20 giây. Tuy nhiên, thực hiện một cái gì đó như IEqualityComparer <T> vẫn là một bài tập hữu ích, nếu chỉ để hiểu cách hoạt động của nó ...
Marc Gravell

Cảm ơn một lần nữa, tôi sẽ để câu trả lời này tồn tại sau đó, trừ khi có ai phản đối mạnh mẽ.
Ash

Mẫu này không thành công khi khởi tạo cho văn hóa tr-TR nếu văn hóa hiện tại là en-US, vì GetHashCode sẽ báo cáo các giá trị khác nhau cho I (U + 0049) và ı (U + 0131), trong khi Equals sẽ coi chúng bằng nhau.
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 sẽ được

   USA 
   INDIA
   UK

3
Vui lòng tránh đăng các đoạn mã mà không có lời giải thích. Chỉnh sửa câu trả lời của bạn và thêm nội dung cho câu trả lời đó. Cảm ơn.
Clijsters

0

Đây là một phiên bản đơn giản hơn nhiều.

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();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.