2009-08-19 48 views
16

Tôi có lớp này:Cách sắp xếp danh sách các đối tượng theo một trường cụ thể trong C#?

public class StatInfo 
{ 
    public string contact; 
    public DateTime date; 
    public string action; 
} 

sau đó tôi có một danh sách StatInfo, nhưng tôi không chắc chắn làm thế nào để sắp xếp nó theo trường ngày. Tôi có nên sử dụng phương pháp sắp xếp không? Tôi có nên tạo của riêng mình không?

var _allStatInfo = new List<StatInfo>(); 
// adding lots of stuff in it 
_allStatInfo.SortByDate??? 

Cách tốt nhất để làm điều này mà không phải viết tấn mã (nếu có thể) là gì?

Cảm ơn

+0

Chờ Jon Skeet để hiển thị. C# của anh ta trong chiều sâu: Những gì bạn cần để làm chủ C# 2 và 3 có một phần lớn về điều đó. – hughdbrown

+0

Quá muộn! Tôi luôn ngạc nhiên khi một trong những câu hỏi của tôi trên C# không nhận được câu trả lời từ Jon Skeet :) – marcgg

+1

tiêu đề là sai. nói "mảng" –

Trả lời

48

Sử dụng LINQ:

var sortedList = _allStatInfo.OrderBy(si => si.date).ToList(); 

Phân loại danh sách ban đầu:

_allStatInfo.Sort(new Comparison<StatInfo>((x, y) => DateTime.Compare(x.date, y.date))); 
+0

Cảm ơn, phương pháp thứ hai đã làm việc. Tôi không sử dụng LINQ vì vậy tôi không thể kiểm tra thứ hai. – marcgg

3

Sử dụng một biểu thức lambda để ánh xạ một cặp để so sánh:

_allStatInfo.Sort((x, y) => x.date - y.date); 
+0

Cảm ơn câu trả lời nhưng tôi gặp lỗi: Không thể chuyển đổi biểu thức lambda thành kiểu System.Collections.Generic.IComparer 'vì nó không phải là loại đại biểu – marcgg

+0

Bạn cần ít nhất C# 3.0 (Visual Studio 2008/bất kỳ phiên bản nào). –

1

Đối với một DateTim e không cần phải so sánh.

_allStatInfo.OrderyBy(d => d.date); 

hoặc

_allStatInfo.OrderByDescending(d => d.Date); 
+0

Cả hai phương thức đều trả về danh sách, vì vậy bạn sẽ cần _allStatInfo = _allStatInfo.OrderBy (d => d.date) .ToList(); – TruthStands

+0

Cảm ơn, nhưng Danh sách <> không có chức năng như vậy nếu tôi không nhầm – marcgg

+0

Tôi đoán đây là LINQ. Tôi không sử dụng LINQ – marcgg

3

Để minh họa Robert C. Cartaino của câu trả lời:

public class StatInfo : IComparable<StatInfo> 
{ 
    public string contact; 
    public DateTime date; 
    public string action; 

    public int CompareTo(StatInfo value) 
    { 
     return this.date.CompareTo(value.date); 
    } 
} 

var _allStatInfo = new List<StatInfo>(); 

// this now sorts by date 
_allStatInfo.Sort(); 

Không phải là giải pháp chung nhất nhưng tốt nếu bạn chỉ đi để sắp xếp theo ngày. Và, như Robert đã nói, bạn vẫn có thể ghi đè lên kiểu mặc định bằng cách chuyển một tham số IComparer tới phương thức sắp xếp.

+0

cảm ơn. Nó không áp dụng thực sự cho tình hình của tôi vì tôi sẽ chỉ sắp xếp theo ngày trong tình huống cụ thể này, nhưng tôi sẽ ghi nhớ điều này sau này – marcgg

+0

@marcgg: Mã trong câu trả lời của tôi sắp xếp theo ngày hành vi mặc định. Vì vậy, nếu bạn chỉ phân loại theo ngày, tôi nghĩ đó là chính xác những gì bạn muốn. –

11

tôi thấy bạn đã có câu trả lời nào, nhưng ...

  1. Bạn có thể tránh được một số xấu xa bằng cách chỉ cần tách các tuyên bố thành hai nửa:

    Comparison<StatInfo> comparison = (x, y) => DateTime.Compare(x.date, y.date); 
    _allStatInfo.Sort(comparison); 
    

    Bạn có thể muốn cũng chỉ xem xét gọi số CompareTo trực tiếp:

    Comparison<StatInfo> comparison = (x, y) => x.date.CompareTo(y.date); 
    _allStatInfo.Sort(comparison); 
    
  2. Bạn có thể tạo IComparer<T> triển khai bằng cách sử dụng lớp học ProjectionComparer của tôi - là một phần của MiscUtil và tôi đã bao gồm phiên bản chưa được chú giải ở cuối số câu trả lời này. Sau đó bạn muốn viết:

    _allStatInfo.Sort(ProjectionComparer<StatInfo>.Create(x => x.date)); 
    
  3. Thậm chí nếu bạn đang sử dụng .NET 2.0, bạn vẫn có thể sử dụng LINQ bằng cách LINQBridge.

Đây là yêu cầu dành cho câu trả lời thứ hai là ProjectionComparer. Hai lớp đầu tiên thực sự chỉ là những người trợ giúp để cho phép suy luận kiểu chung tốt hơn.

public static class ProjectionComparer 
{ 
    public static ProjectionComparer<TSource, TKey> Create<TSource, TKey> 
     (Func<TSource, TKey> projection) 
    { 
     return new ProjectionComparer<TSource, TKey>(projection); 
    } 

    public static ProjectionComparer<TSource, TKey> Create<TSource, TKey> 
     (TSource ignored, Func<TSource, TKey> projection) 
    { 
     return new ProjectionComparer<TSource, TKey>(projection); 
    } 

} 

public static class ProjectionComparer<TSource> 
{ 
    public static ProjectionComparer<TSource, TKey> Create<TKey> 
     (Func<TSource, TKey> projection) 
    { 
     return new ProjectionComparer<TSource, TKey>(projection); 
    } 
} 

public class ProjectionComparer<TSource, TKey> : IComparer<TSource> 
{ 
    readonly Func<TSource, TKey> projection; 
    readonly IComparer<TKey> comparer; 

    public ProjectionComparer(Func<TSource, TKey> projection) 
     : this (projection, null) 
    { 
    } 

    public ProjectionComparer(Func<TSource, TKey> projection, 
           IComparer<TKey> comparer) 
    { 
     projection.ThrowIfNull("projection"); 
     this.comparer = comparer ?? Comparer<TKey>.Default; 
     this.projection = projection; 
    } 

    public int Compare(TSource x, TSource y) 
    { 
     // Don't want to project from nullity 
     if (x==null && y==null) 
     { 
      return 0; 
     } 
     if (x==null) 
     { 
      return -1; 
     } 
     if (y==null) 
     { 
      return 1; 
     } 
     return comparer.Compare(projection(x), projection(y)); 
    } 
} 
+1

Bạn đang nói mã của tôi là xấu? :-( –

+0

Oh cảm ơn, chỉ khi tôi nói rằng tôi đã không nhận được câu trả lời từ bạn về một câu hỏi C# :) Tôi sẽ giữ câu trả lời của Ben được chấp nhận nhưng tôi upvoted của bạn và tôi chắc chắn nó sẽ được ngay dưới đây – marcgg

+1

@Ben: Tôi chỉ không thích rằng nhiều dấu ngoặc nếu tôi có thể giúp nó :) –

1

nó làm việc cho tôi ُSorting array of custom type using delegate

// sort array by name 
Array.Sort(users, delegate(User user1, User user2) 
      { 
      return user1.Name.CompareTo(user2.Name); 
      }); 
// write array (output: Betty23 Lisa25 Susan20) 
foreach (User user in users) Console.Write(user.Name + user.Age + " "); 
+0

Cảm ơn, chỉ có câu trả lời mà làm việc cho tôi. – lama12345

Các vấn đề liên quan