2011-02-06 33 views
24

tôi đang làm việc trên một ứng dụng mà nhập khẩu hàng ngàn dòng mà mỗi dòng có một định dạng như thế này:C# Regex.Split: Xóa kết quả rỗng

|* 9070183020 |04.02.2011 |107222  |M/S SUNNY MEDICOS     |GHAZIABAD       |  32,768.00 | 

Tôi đang sử dụng Regex sau để phân chia các dòng vào dữ liệu tôi cần:

Regex lineSplitter = new Regex(@"(?:^\|\*|\|)\s*(.*?)\s+(?=\|)"); 
string[] columns = lineSplitter.Split(data); 

foreach (string c in columns) 
    Console.Write("[" + c + "] "); 

này được đưa ra cho tôi những kết quả sau:

[] [9070183020] [] [04.02.2011] [] [107222] [] [M/S SUNNY MEDICOS] [] [GHAZIABAD] [] [32,768.00] [|] 

N Tôi có hai câu hỏi.
1. Làm cách nào để xóa kết quả trống. Tôi biết tôi có thể sử dụng:

string[] columns = lineSplitter.Split(data).Where(s => !string.IsNullOrEmpty(s)).ToArray(); 

nhưng có phương pháp tích hợp nào để xóa kết quả trống không?

2. Làm thế nào tôi có thể tháo ống cuối cùng?

Cảm ơn bạn đã được trợ giúp.
Kính trọng,
Yogesh.

CHỈNH SỬA:
Tôi nghĩ câu hỏi của tôi hơi bị hiểu lầm. Nó không bao giờ về làm thế nào tôi có thể làm điều đó. Chỉ khoảng làm cách nào tôi có thể làm điều đó bằng cách thay đổi Regex trong mã trên.

Tôi biết rằng tôi có thể thực hiện theo nhiều cách. Tôi đã thực hiện nó với mã đề cập ở trên với một điều khoản Where và với một cách thay thế mà cũng là (hơn hai lần) nhanh hơn:

Regex regex = new Regex(@"(^\|\*\s*)|(\s*\|\s*)"); 
data = regex.Replace(data, "|"); 

string[] columns = data.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); 

Thứ hai, như một trường hợp thử nghiệm, hệ thống của tôi có thể phân tích cú pháp 92k + ​​như vậy các dòng trong chưa đầy 1,5 giây trong phương thức gốc và trong ít hơn 700 mili giây trong phương pháp thứ hai, nơi tôi sẽ không bao giờ tìm thấy hơn một vài nghìn trong các trường hợp thực, vì vậy tôi không nghĩ rằng tôi cần suy nghĩ về tốc độ ở đây . Theo tôi nghĩ về tốc độ trong trường hợp này là tối ưu hóa sớm.

Tôi đã tìm thấy câu trả lời cho câu hỏi đầu tiên của tôi: nó không thể được thực hiện với Split như không có tùy chọn như vậy được xây dựng trong

Vẫn đang tìm kiếm câu trả lời cho câu hỏi thứ hai của tôi..

+0

Để trả lời câu hỏi đầu tiên của bạn, tôi tin rằng phần nhóm của regex phải là '@" (. +?) "'. Nếu không nó sẽ có thể phù hợp với khoảng trống (đó là những gì bạn có bây giờ). –

+0

Những vấn đề nghiêm trọng trong trường hợp này là Jeff. Nó sẽ cho kết quả chính xác tương tự. – Yogesh

+0

Cũng giống như một lưu ý khi bạn đang đề cập đến hàng ngàn mục: Sử dụng String.Split và sau đó thực hiện một số thao tác String khác nhanh hơn nhiều so với sử dụng Regex ở vị trí đầu tiên. – Foxfire

Trả lời

37
Regex lineSplitter = new Regex(@"[\s*\*]*\|[\s*\*]*"); 
var columns = lineSplitter.Split(data).Where(s => s != String.Empty); 

hoặc bạn chỉ có thể làm:

string[] columns = data.Split(new char[] {'|'}, StringSplitOptions.RemoveEmptyEntries); 
foreach (string c in columns) this.textBox1.Text += "[" + c.Trim(' ', '*') + "] " + "\r\n"; 

Và không có, không có tùy chọn để loại bỏ các mục trống cho RegEx.Split như là dành cho String.split.

Bạn cũng có thể sử dụng kết quả phù hợp.

+0

+1 để trả lời câu hỏi đầu tiên của tôi. Đây cũng là những gì tôi tìm thấy đọc trên mạng và tài liệu msdn. – Yogesh

+0

Ngoài ra, nếu bạn thử RegEx của tôi, bạn sẽ thấy không có giá trị rỗng trừ khi bắt đầu và ở cuối mảng. –

+0

Đánh dấu câu trả lời của bạn đã được chọn khi bạn đến gần nhất. Tôi đang sử dụng phương pháp thứ hai tôi đã đề cập trong câu hỏi của mình để được nhanh hơn. Cảm ơn. – Yogesh

0

Làm thế nào về điều này:

giả sử chúng ta có một dòng:

line1="|* 9070183020 |04.02.2011 |107222  |M/S SUNNY MEDICOS     |GHAZIABAD       |  32,768.00 |"; 
kết quả

chúng ta có thể đã yêu cầu như:

string[] columns =Regex.Split(line1,"|"); 
foreach (string c in columns) 
     c=c.Replace("*","").Trim(); 

Điều này sẽ cho kết quả sau:

[9070183020] [04.02.2011] [107222] [M/S SUNNY MEDICOS] [GHAZIABAD] [32,768.00] 
0

Tôi có thể có wro ng ý tưởng ở đây, nhưng bạn chỉ muốn tách chuỗi data bằng cách sử dụng '|' ký tự như một dấu phân cách? Trong trường hợp đó bạn couldtry:

string[] result = data.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries).Select(d => d.Trim()).ToArray(); 

này sẽ trả về tất cả các lĩnh vực, không có khoảng và với các lĩnh vực có sản phẩm nào gỡ bỏ. Bạn có thể làm những gì bạn thích trong phần Select để định dạng kết quả, ví dụ:

.Select(d => "[" + d.Trim() + "]").ToArray(); 
1

Là một thay thế để tách, mà luôn luôn sẽ gây ra rắc rối khi delimiters bạn cũng có mặt lúc bắt đầu và kết thúc của đầu vào, bạn có thể thử phù hợp với các nội dung bên trong các đường ống:

foreach (var token in Regex.Matches(input, @"\|\*?\s*(\S[^|]*?)\s*(?=\|)")) 
{ 
    Console.WriteLine("[{0}]", token.Groups[1].Value); 
} 

// Prints the following: 
// [9070183020] 
// [04.02.2011] 
// [107222] 
// [M/S SUNNY MEDICOS] 
// [GHAZIABAD] 
// [32,768.00] 
0

Don 't sử dụng một regex ở tất cả trong trường hợp của bạn. Có vẻ như bạn không cần một và regexes chậm hơn nhiều (và có chi phí cao hơn nhiều) so với trực tiếp sử dụng các hàm chuỗi.

Vì vậy, sử dụng hơi như:

const Char[] splitChars = new Char[] {'|'}; 

string[] splitData = data.Split(splitChars, StringSplitOptions.RemoveEmptyEntries) 
2

Tôi nghĩ rằng điều này có thể làm việc như một tương đương để loại bỏ chuỗi rỗng:

string[] splitter = Regex.Split(textvalue,@"\s").Where(s => s != String.Empty).ToArray<string>(); 
+0

Ví dụ tốt cho những điều nhỏ mà LINQ làm tốt hơn nhiều :) –

0

Dựa trên câu trả lời tuyệt vời Jandek của @Jaroslav, tôi đã viết một extension method, tôi đặt ở đây, có thể nó có thể tiết kiệm thời gian của bạn.

/// <summary> 
/// String.Split with RemoveEmptyEntries option for clean up empty entries from result 
/// </summary> 
/// <param name="s">Value to parse</param> 
/// <param name="separator">The separator</param> 
/// <param name="index">Hint: pass -1 to get Last item</param> 
/// <param name="wholeResult">Get array of split value</param> 
/// <returns></returns> 
public static object CleanSplit(this string s, char separator, int index, bool wholeResult = false) 
{ 
    if (string.IsNullOrWhiteSpace(s)) return ""; 

    var split = s.Split(new char[] { separator }, StringSplitOptions.RemoveEmptyEntries); 

    if (wholeResult) return split; 

    if (index == -1) return split.Last(); 

    if (split[index] != null) return split[index]; 

    return ""; 
} 
0

1. Làm thế nào để loại bỏ các kết quả có sản phẩm nào?

Bạn có thể sử dụng LINQ để loại bỏ tất cả các mục mà đều bình đẳng để string.Empty:

string[] columns = lineSplitter.Split(data); 
columns = columns.ToList().RemoveAll(c => c.Equals(string.Empty)).ToArray(); 

2. Làm thế nào tôi có thể loại bỏ các đường ống cuối cùng?

Bạn có thể sử dụng LINQ đây để loại bỏ tất cả các mục tương ứng với nhân vật bạn muốn loại bỏ:

columns = columns.ToList().RemoveAll(c => c.Equals("|")).ToArray(); 
0

sử dụng giải pháp này:

string stringwithDelemeterNoEmptyValues= string.Join(",", stringwithDelemeterWithEmptyValues.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)); 
Các vấn đề liên quan