Sắp xếp danh sách lớp tùy chỉnh <T>


112

Tôi muốn sắp xếp danh sách của tôi với datetài sản.

Đây là lớp tùy chỉnh của tôi:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Test.Web
{
    public class cTag
    {
        public int id { get; set; }
        public int regnumber { get; set; }
        public string date { get; set; }
    }
}

Đây là cái Listmà tôi muốn sắp xếp:

List<cTag> Week = new List<cTag>();

Những gì tôi muốn làm là sắp xếp Danh sách theo thuộc datetính của lớp cTag. Ngày tháng có định dạng: dd.MM.yyyy.

Tôi đọc một cái gì đó về IComparablegiao diện, nhưng không biết làm thế nào để sử dụng nó.

Câu trả lời:


143

Một cách để làm điều này là với delegate

List<cTag> week = new List<cTag>();
// add some stuff to the list
// now sort
week.Sort(delegate(cTag c1, cTag c2) { return c1.date.CompareTo(c2.date); });

98
Bạn cũng có thể viết những điều tương tự với một biểu thức lambda:list.Sort((a,b) => a.date.CompareTo(b.date));
Xavier Poinas

2
@Xavier vì lý do nào đó mà tâm trí tôi vẫn luôn chuyển đến các vị từ đầu tiên, mặc dù bạn hoàn toàn đúng 100% rằng biểu thức Lambda của bạn sẽ hoàn thành công việc và có lẽ dễ đọc / hiểu hơn.
ahsteele

làm thế nào để điều này, hoặc làm thế nào bạn, phá vỡ sự ràng buộc một cách nhất quán bằng cách sử dụng biểu thức lambda? Điều gì sẽ xảy ra nếu a.date == b.date ở đây? list.Sort ((a, b) => a.date.CompareTo (b.date)); Điều này có tạo ra vấn đề khi lưới phân trang và hai lưới này tình cờ rơi vào các trang khác nhau không?
TheEmirOfGroofunkistan

1
@TheEmirOfGroofunkistan mà tất cả phụ thuộc vào cách CompareTođược triển khai. IComparablengười được cấp phép rằng một lớp sẽ có phương thức nhưng nó thực hiện như thế nào so sánh đó là tùy thuộc vào người tạo lớp. Không chắc về cách Date thực hiện ICompare, nhưng thường thì tôi đã thấy các nhà phát triển sử dụng các tham số thứ tự đã được chuyển để phá vỡ ràng buộc khi các giá trị bằng nhau. hth
ahsteele

51

Bạn đúng rằng lớp cTag của bạn phải triển khai IComparable<T>giao diện. Sau đó, bạn chỉ có thể gọi Sort()trong danh sách của mình.

Để triển khai IComparable<T>giao diện, bạn phải thực hiện CompareTo(T other)phương pháp. Cách dễ nhất để làm điều này là gọi phương thức CompareTo của trường bạn muốn so sánh, trong trường hợp của bạn là ngày tháng.

public class cTag:IComparable<cTag> {
    public int id { get; set; }
    public int regnumber { get; set; }
    public string date { get; set; }
    public int CompareTo(cTag other) {
        return date.CompareTo(other.date);
    }
}

Tuy nhiên, điều này sẽ không sắp xếp tốt, bởi vì điều này sẽ sử dụng sắp xếp cổ điển trên chuỗi (vì bạn đã khai báo ngày là chuỗi). Vì vậy, tôi nghĩ cách tốt nhất nên làm là xác định lại lớp và khai báo ngày không phải là chuỗi, mà là DateTime. Mã sẽ gần như giữ nguyên:

public class cTag:IComparable<cTag> {
    public int id { get; set; }
    public int regnumber { get; set; }
    public DateTime date { get; set; }
    public int CompareTo(cTag other) {
        return date.CompareTo(other.date);
    }
}

Điều duy nhất bạn phải làm khi tạo thể hiện của lớp để chuyển đổi chuỗi chứa ngày của bạn thành kiểu DateTime, nhưng nó có thể được thực hiện dễ dàng, ví dụ như bằng DateTime.Parse(String)phương thức.


38

Đối với trường hợp này, bạn cũng có thể sắp xếp bằng LINQ:

week = week.OrderBy(w => DateTime.Parse(w.date)).ToList();

12
List<cTag> week = new List<cTag>();
week.Sort((x, y) => 
    DateTime.ParseExact(x.date, "dd.MM.yyyy", CultureInfo.InvariantCulture).CompareTo(
    DateTime.ParseExact(y.date, "dd.MM.yyyy", CultureInfo.InvariantCulture))
);

9

Điều đầu tiên, nếu thuộc tính date đang lưu trữ một ngày tháng, hãy lưu trữ nó bằng cách sử dụng DateTime. Nếu bạn phân tích cú pháp ngày thông qua loại bạn phải phân tích cú pháp cho từng mục được so sánh, điều đó không hiệu quả lắm ...

Sau đó, bạn có thể tạo IComparer:

public class TagComparer : IComparer<cTag>
{
    public int Compare(cTag first, cTag second)
    {
        if (first != null && second != null)
        {
            // We can compare both properties.
            return first.date.CompareTo(second.date);
        }

        if (first == null && second == null)
        {
            // We can't compare any properties, so they are essentially equal.
            return 0;
        }

        if (first != null)
        {
            // Only the first instance is not null, so prefer that.
            return -1;
        }

        // Only the second instance is not null, so prefer that.
        return 1;
    }
}

var list = new List<cTag>();
// populate list.

list.Sort(new TagComparer());

Bạn thậm chí có thể làm điều đó với tư cách là đại biểu:

list.Sort((first, second) =>
          {
              if (first != null && second != null)
                  return first.date.CompareTo(second.date);

              if (first == null && second == null)
                  return 0;

              if (first != null)
                  return -1;

              return 1;
          });

6

Bạn đúng - bạn cần phải triển khai IComp so sánh được. Để làm điều này, chỉ cần khai báo lớp của bạn:

public MyClass : IComparable
{
  int IComparable.CompareTo(object obj)
  {
  }
}

Trong CompareTo, bạn chỉ cần triển khai thuật toán so sánh tùy chỉnh của mình (bạn có thể sử dụng các đối tượng DateTime để thực hiện việc này, nhưng chỉ cần chắc chắn kiểm tra loại "obj" trước). Để biết thêm thông tin, hãy xem tại đâyđây .


7
IComparable<T>có lẽ sẽ là lựa chọn tốt hơn, vì nó được chọn để ưu tiên IComparable: msdn.microsoft.com/en-us/library/b0zbh7b6.aspx
Richard Szalay,

5

Bạn có thể sử dụng linq:

var q = from tag in Week orderby Convert.ToDateTime(tag.date) select tag;
List<cTag> Sorted = q.ToList()

3

nhìn vào phương thức Sắp xếp quá tải của lớp Danh sách. có một số cách để làm điều đó. một trong số chúng: lớp tùy chỉnh của bạn phải triển khai giao diện ICompABLE, sau đó bạn cam sử dụng phương thức Sắp xếp của lớp Danh sách.


3

Cảm ơn cho tất cả các câu trả lời nhanh chóng.

Đây là giải pháp của tôi:

Week.Sort(delegate(cTag c1, cTag c2) { return DateTime.Parse(c1.date).CompareTo(DateTime.Parse(c2.date)); });

Cảm ơn


2
YourVariable.Sort((a, b) => a.amount.CompareTo(b.amount));
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.