2009-06-02 40 views
8

Tôi đã hơn một ngàn thư mục, mỗi thư mục chứa một hoặc nhiều tập tin có tên sau:Tuỳ chỉnh LINQ đặt hàng

Unordered:

 
Alison.ext 
Heather.ext 
Molly.ext 
Paula.ext 
Sam.ext 

Ordered:

 
Molly.ext 
Sam.ext 
Heather.ext 
Alison.ext 
Paula.ext 

Tôi muốn để viết một biểu thức để sắp xếp danh sách này như được mô tả ở trên.

Trả lời

14
//Creating a dictionary with the custom order 
var order = "MSHAP"; 
var orderDict = order.Select((c,i)=>new {Letter=c, Order=i}) 
        .ToDictionary(o => o.Letter, o => o.Order); 

var list = new List<string>{"A.ext", "H.ext", "M.ext", "P.ext", "S.ext"}; 

//Ordering by the custom criteria 
var result = list.OrderBy(item => orderDict[item[0]]); 

Thay vì gọi orderDict [item [0]] bạn có thể có một phương pháp helper tốt đẹp mà quan tâm đến các trường hợp rìa (chữ không tồn tại, null, vv o n). Nhưng đó là ý tưởng.

+0

@Yann Schwartz: Đó chỉ là giả tên file, phím chữ cái tôi muốn sử dụng là chữ cái đầu tiên của tập tin. Cảm ơn! – Chris

+0

Xin lỗi. Tôi nghĩ rằng bạn muốn có một thứ tự chữ cái tùy chỉnh (tôi đã nhìn thấy những điều xa lạ :-)) –

+0

euh đó không phải là những gì anh ta muốn? Tôi nghĩ anh ấy cũng muốn điều đó .. –

0

Bạn đã không đề cập chính xác những gì sắp xếp của các đối tượng mà bạn có trong danh sách, nhưng giả sử nó là một số thỏa thuận chung chung như vậy:

public class File { 
    public string FileName { ... } 
    public long FileSize { ... } 
    /* elided */ 
} 

Sau đó, đưa ra một IEnumerable gọi, nói rằng, files, bạn có thể chỉ cần làm:

var result = files.OrderBy(f => f.FileName); 
1
List<char> sortKeys = new List<char> { 'M', 'S', 'H', 'A', 'P' }; 
sortKeys.Reverse(); 
List<FileInfo> files = new List<FileInfo>(6); 

foreach(char sortKey in sortKeys) 
{ 
    var topFiles = files.Where(file => file.Name.StartsWith(sortKey.ToString())); 
    var remainingFiles = files.Except(topFiles); 
    files = topFiles.Concat(remainingFiles).ToList(); 
} 

chưa được kiểm tra và tôi chắc chắn rằng có những cách nhanh hơn, nhưng ít nhất nó với các công cụ LINQ như bạn hỏi :-)

chỉnh sửa: Tôi chỉ thấy các chỉnh sửa trên bài viết của bạn và bây giờ tôi không có bất kỳ ý tưởng nữa những gì bạn thực sự muốn làm, vì vậy mã của tôi có lẽ là vô ích cho bạn ..

+0

Mục đích ở đây là âm thanh.Đó là hiệu suất đáng ngờ để liệt kê bộ sưu tập một lần cho mỗi khóa đặt hàng. Ngoài ra, nó là đáng sợ để xem xét thực hiện trì hoãn của Linq và sự tương tác của Concat và ngoại trừ. topFiles.Concat (files.Except (topFiles)) –

6

Dưới đây là một phương pháp mà tạo ra các phím để đặt hàng

public int OrderKey(string fileName) 
{ 
    char first = fileName[0]; 
    int result = 
    first == 'M' ? 1 : 
    first == 'S' ? 2 : 
    first == 'H' ? 3 : 
    first == 'A' ? 4 : 
    first == 'P' ? 5 : 
    6; 
    return result; 
} 

Dưới đây là làm thế nào để gọi nó là:

List<File> ordered = Files.OrderBy(f => OrderKey(f.FileName)).ToList(); 
+0

Thx, hoạt động hoàn hảo. Đã phải đặt hàng mã chuỗi (được sửa đổi để sử dụng chuỗi không phải char). Đã phải sắp xếp thứ hạng, không phải là alpha. Và thậm chí bắt các mã không có trong danh sách, đặt chúng cuối cùng. –

0

Bạn có thể lưu trữ danh sách thứ tự mong muốn trong một mảng

int[] iIndex = {3,2,0,4, 1}; 

Say str giữ Danh sách không có thứ tự của bạn

List<string> str = new List<string>(); 
str.Add("Alison.ext"); 
str.Add("Heather.ext"); 
. 
. 
. 

Thêm danh sách của bạn và tương ứng đặt hàng vào một datatable

DataTable dt = new DataTable(); 
       dt.Columns.Add("Order", typeof(Int32)); 
       dt.Columns.Add("Name"); 

       for (int iCount =0; iCount< str.Count ; iCount ++) 
       { 
        DataRow drow1 = dt.NewRow(); 
        drow1[0] = iIndex[iCount]; 
        drow1[1] = str[iCount]; 
        dt.Rows.Add(drow1); 

       } 
       dt.AcceptChanges(); 

Fynally thứ tự danh sách yuor để có được danh sách dự kiến ​​yuor

var result = from ls in dt.AsEnumerable() 
         orderby ls.Field<int>("Order") 
         select ls;