2011-08-10 47 views
11

Tôi có danh sách các chuỗi (tên tệp thực sự) và tôi muốn chỉ giữ lại các chuỗi khớp với biểu thức lọc như: \*_Test.txt.Cách lọc danh sách các chuỗi phù hợp với mẫu

Điều gì sẽ là tốt nhất để đạt được điều này?

Dưới đây là câu trả lời mà tôi đã đưa ra:

List<string> files = new List<string>(); 
files.Add("MyFile1.csv"); 
files.Add("MyFile1_Test.txt"); 
files.Add("MyFile2.csv"); 
files.Add("MyFile2_Test.txt"); 
files.Add("MyFile3.csv"); 
files.Add("MyFile3_Test.txt"); 
files.Add("MyFile_Testtxttxt.txt"); 

// Define a filter 
string filter = "*_Test.txt"; 

// Make the filter regex safe 
foreach (char x in @"\+?|{[()^$.#") 
    filter = filter.Replace(x.ToString(), @"\" + x.ToString()); 

filter = string.Format("^{0}$",filter.Replace("*", ".*")); 

// Old School 
List<string> resultList1 = files.FindAll(delegate(string s) { return Regex.IsMatch(s, filter, RegexOptions.IgnoreCase); }); 

// Version using LINQ 
List<string> resultList2 = files.Where(x => Regex.IsMatch(x, filter, RegexOptions.IgnoreCase) == true).ToList(); 
+0

tôi muốn bộ lọc để được linh hoạt vì vậy tôi có thể sử dụng \ * \ * hoặc \ * .t \ * hoặc bất kỳ số kết hợp nào . Việc xóa \ * sẽ không cho tôi kết quả khớp một phần. – TeamWild

+0

Eeep, một sửa chữa cho câu trả lời của tôi, bạn cần phải thay đổi string.Format thành '("^{0} $ ")' nếu không nó sẽ tìm thấy '" fish_Test.txtWIBBLE "' –

Trả lời

18

Bạn có thể wan để sử dụng cụm từ thông dụng cho điều này nếu các mẫu của bạn sẽ phức tạp ....

bạn có thể sử dụng cụm từ thông dụng thích hợp làm bộ lọc của mình (ví dụ: ví dụ cụ thể của bạn là new Regex(@"^.*_Test\.txt$") hoặc bạn có thể áp dụng thuật toán chuyển đổi.

Dù bằng cách nào bạn có thể sử dụng linq để áp dụng regex.

ví dụ

var myRegex=new Regex(@"^.*_Test\.txt$"); 
List<string> resultList=files.Where(myRegex.IsMatch).ToList(); 

Một số người có thể nghĩ rằng câu trả lời ở trên là không chính xác, nhưng bạn có thể sử dụng một nhóm phương pháp thay vì một lambda. Nếu bạn muốn toàn bộ lamda bạn sẽ sử dụng:

var myRegex=new Regex(@"^.*_Test\.txt$"); 
List<string> resultList=files.Where(f => myRegex.IsMatch(f)).ToList(); 

hoặc không LINQ

List<string> resultList=files.FindAll(delegate(string s) { return myRegex.IsMatch(s);}); 

nếu bạn đang chuyển đổi bộ lọc chuyển đổi đơn giản sẽ là

var myFilter="*_Test.txt"; 
var myRegex=new Regex("^" + myFilter.Replace("*",".*") +"$"); 

Sau đó, bạn có thể cũng có các bộ lọc như "*Test*.txt" với phương pháp này.

Tuy nhiên, nếu bạn đi xuống tuyến đường chuyển đổi này, bạn sẽ cần đảm bảo bạn đã thoát khỏi tất cả các ký tự cụm từ thông dụng đặc biệt, ví dụ: "." trở thành @ ".", "(" trở thành @ "(" vv .......

Chỉnh sửa - Ví dụ thay thế là TOO đơn giản vì nó không chuyển đổi. Vì vậy, nó sẽ tìm thấy "fish_Textxtxt" để thoát atleast .

nên

string myFilter="*_Test.txt"; 
foreach(char x in @"\+?|{[()^$.#") { 
    myFilter = myFilter.Replace(x.ToString(),@"\"+x.ToString()); 
} 
Regex myRegex=new Regex(string.Format("^{0}$",myFilter.Replace("*",".*"))); 
7

Các bạn đã thử LINQ:

List<string> resultList = files.Where(x => x.EndsWith("_Test.txt")).ToList(); 

hoặc nếu bạn đang chạy này trên một số phiên bản cũ/di sản NET (< 3.5):

List<string> resultList = files.FindAll(delegate(string s) { 
    return s.EndsWith("_Test.txt"); 
}); 
+0

Và bạn có thể thêm regex vào đó, nếu bạn muốn một cái gì đó linh hoạt hơn, nhưng có thể phức tạp. http://msdn.microsoft.com/en-us/library/ms228595% 28v = VS.100% 29.aspx – Johnny5

+0

Tôi đã hy vọng sẽ có một cách nhanh chóng mà không sử dụng regex vì luôn luôn kết thúc trong một nhức đầu. Tôi có thể sử dụng LINQ vì vậy sẽ thử nó và xem những gì sẽ xảy ra. – TeamWild

1

này đã làm việc cho tôi và khá đơn giản:.

List<string> keys = new List<string>(); 
//populate your list 
var myregex = new Regex("^.+$"); 
List<string> matchlist = keys.Where(i=>myregex.IsMatch(i)).ToList(); 
Các vấn đề liên quan