2012-07-18 44 views
7

Tôi cần xóa các ký tự khỏi chuỗi không nằm trong phạm vi từ Ascii từ 32 đến 175, mọi thứ khác phải được loại bỏ.Cách tốt hơn để xóa các ký tự không phải là ASCII 32 đến 175 C#

Tôi không biết rõ nếu RegExp có thể là giải pháp tốt nhất thay vì sử dụng một cái gì đó như .replace() hoặc .remove() pasing mỗi ký tự không hợp lệ hoặc cái gì khác.

Mọi trợ giúp sẽ được đánh giá cao.

+0

Bạn có thể không chỉ xóa chúng bằng cách lập chỉ mục chuỗi bình thường không? Chuỗi đích có thể được phân bổ như chiều dài giống như chuỗi nguồn vì nó được bảo đảm là có cùng độ dài hoặc ngắn hơn. Sau đó, chỉ cần sao chép các ký tự hợp lệ trong một vòng lặp? Nó chỉ là hai so sánh để kiểm tra hợp lệ. –

+0

Và một bản sao của 'char []' bởi vì chuỗi sẽ có cùng độ dài như trước, chỉ với 0-padding theo cách đó. – Joey

Trả lời

16

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

Regex.Replace(myString, @"[^\x20-\xaf]+", ""); 

Các regex ở đây bao gồm một lớp nhân vật ([...]) bao gồm tất cả các nhân vật không (^ vào lúc bắt đầu của lớp) trong khoảng từ U + 0020 đến U + 00AF (32–175, được biểu thị bằng ký hiệu thập lục phân). Theo như các biểu thức thông thường, điều này là khá cơ bản, nhưng có thể khiến ai đó không quen thuộc với nó.

Nhưng bạn có thể đi con đường khác cũng như:

new string(myString.Where(c => (c >= 32) && (c <= 175)).ToArray()); 

này có lẽ phụ thuộc chủ yếu vào những gì bạn cảm thấy thoải mái hơn với việc đọc sách. Nếu không có nhiều kinh nghiệm regex tôi muốn nói thứ hai sẽ rõ ràng hơn.

Một vài phép đo hiệu suất, 10000 vòng mỗi, chỉ trong vài giây:

2000 characters, the first 143 of which are between 32 and 175 
    Regex without +       4.1171 
    Regex with +        0.4091 
    LINQ, where, new string     0.2176 
    LINQ, where, string.Join     0.2448 
    StringBuilder (xanatos)     0.0355 
    LINQ, horrible (HatSoft)     0.4917 
2000 characters, all of which are between 32 and 175 
    Regex without +       0.4076 
    Regex with +        0.4099 
    LINQ, where, new string     0.3419 
    LINQ, where, string.Join     0.7412 
    StringBuilder (xanatos)     0.0740 
    LINQ, horrible (HatSoft)     0.4801 

Vì vậy, có, cách tiếp cận của tôi là :-) chậm nhất. Bạn có lẽ nên đi với câu trả lời của xanatos và bọc nó trong một phương pháp với một cái tên đẹp, rõ ràng. Đối với việc sử dụng nội tuyến hoặc những điều nhanh chóng và bẩn thỉu hoặc nơi hiệu suất không quan trọng, tôi có thể sử dụng regex.

+0

Bạn nên sử dụng '+' để làm cho nó nhanh hơn –

+0

cảm ơn, lựa chọn phương pháp tiếp cận đó là một lựa chọn tốt, regex quá để phân tích nó và biết thêm về nó. – FabianSilva

+0

thử nghiệm hiệu suất tốt đẹp, tôi thấy rằng xanatos là tốt nhất nếu phải loại bỏ các ký tự từ một văn bản lớn, cảm ơn đã dành thời gian để kiểm tra nó, trong trường hợp của tôi, tôi sẽ loại bỏ các ký tự từ chuỗi ngắn và có vẻ như linq là cách để đi cho tôi, không phải là người biểu diễn nhiều hơn, không viết ngắn hơn, nhưng dễ áp ​​dụng/viết trong câu 1 dòng :) cảm ơn bạn, xanatos và tất cả người dùng đã trả lời – FabianSilva

3

Sử dụng regex [^\x20-\xAF]+ và thay thế nó bằng chuỗi rỗng ""

Regex.Replace(str, @"[^\x20-\xAF]+", ""); 
7

Bởi vì tôi nghĩ rằng nếu bạn không biết làm thế nào để viết một Regex bạn không nên sử dụng nó, đặc biệt là đối với một cái gì đó đơn giản như vậy:

var sb = new StringBuilder(); 

foreach (var c in str) 
{ 
    if (c >= 32 && c <= 175) 
    { 
     sb.Append(c); 
    } 
} 

var str2 = str.ToString(); 
+0

Đó là những gì tôi nghĩ. Một cuộc gọi regex có vẻ hơi OTT cho điều này? –

+0

Tôi có một cái gì đó rất giống với điều này, ngoại trừ một phần bổ sung mà cố gắng để chuyển đổi ascii cao phổ biến vào thay thế ascii thấp, tức là '' 'thành' "' – asawyer

+0

@FabianSilva Tôi không nghĩ cách tốt nhất để học một cái gì đó là đi đến một bảng và hỏi "bạn có thể viết nó cho tôi bằng một ngôn ngữ mà tôi không biết?" – xanatos

1

Làm thế nào về việc sử dụng LINQ cách này

string text = (from c in "AAA hello aaaa #### Y world" 
       let i = (int) c where i < 32 && i > 175 select c) 
       .Aggregate("", (current, c) => current + c); 
+0

cảm ơn cho câu trả lời, biểu thức LINQ của bạn là một giải pháp tốt nhưng dường như với tôi rằng biểu thức joey dễ hiểu hơn. – FabianSilva

+0

@FabianSilva lol trả lời tốt đẹp – HatSoft

+0

btw cảm ơn cho giải pháp thay thế này bằng cách sử dụng let và tổng hợp – FabianSilva

1
static unsafe string TrimRange(string str, char from, char to) 
{ 
    int count = 0; 

    for (int i = 0; i < str.Length; i++) 
    { 
     char ch = str[i]; 

     if ((ch >= from) && (ch <= to)) 
     { 
      count++; 
     } 
    } 

    if (count == 0) 
     return String.Empty; 

    if (count == str.Length) 
     return str; 

    char * result = stackalloc char[count]; 

    count = 0; 

    for (int i = 0; i < str.Length; i++) 
    { 
     char ch = str[i]; 

     if ((ch >= from) && (ch <= to)) 
     { 
      result[count ++] = ch; 
     } 
    } 

    return new String(result, 0, count); 
} 
Các vấn đề liên quan