成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

.NET中刪除空白字符串的10大方法

開發 后端
我們有無數方法可用于刪除字符串中的所有空白。大部分都能夠在絕大多數的用例中很好工作,但在某些對時間敏感的應用程序中,是否采用最快的方法可能就會造成天壤之別。

我們有無數方法可用于刪除字符串中的所有空白,但是哪個更快呢?

介紹

我們有無數方法可用于刪除字符串中的所有空白。大部分都能夠在絕大多數的用例中很好工作,但在某些對時間敏感的應用程序中,是否采用最快的方法可能就會造成天壤之別。

如果你問空白是什么,那說起來還真是有些亂。許多人認為空白就是SPACE 字符(UnicodeU+0020,ASCII 32,HTML ),但它實際上還包括使得版式水平和垂直出現空格的所有字符。事實上,這是一整類定義為Unicode字符數據庫的字符。

本文所說的空白,不但指的是它的正確定義,同時也包括string.Replace(” “, “”)方法。

這里的基準方法,將刪除所有頭尾和中間的空白。這就是文章標題中“所有空白”的含義。

[[154082]]

背景

這篇文章一開始是出于我的好奇心。事實上,我并不需要用最快的算法來刪除字符串中的空白。

檢查空白字符

檢查空白字符很簡單。所有你需要的代碼就是:

  1. char wp = ' '
  2. char a = 'a'
  3. Assert.True(char.IsWhiteSpace(wp)); 
  4. Assert.False(char.IsWhiteSpace(a)); 

但是,當我實現手動優化刪除方法時,我意識到這并不像預期得那么好。一些源代碼在微軟的參考源代碼庫的char.cs挖掘找到:

 

  1. public static bool IsWhiteSpace(char c) { 
  2.     if (IsLatin1(c)) { 
  3.         return (IsWhiteSpaceLatin1(c)); 
  4.     } 
  5.     return CharUnicodeInfo.IsWhiteSpace(c); 
  6.  
  7. 然后CharUnicodeInfo.IsWhiteSpace成了: 
  8.  
  9. internal static bool IsWhiteSpace(char c) 
  10.     UnicodeCategory uc = GetUnicodeCategory(c); 
  11.     // In Unicode 3.0, U+2028 is the only character which is under the category "LineSeparator". 
  12.     // And U+2029 is th eonly character which is under the category "ParagraphSeparator". 
  13.     switch (uc) { 
  14.         case (UnicodeCategory.SpaceSeparator): 
  15.         case (UnicodeCategory.LineSeparator): 
  16.         case (UnicodeCategory.ParagraphSeparator): 
  17.             return (true); 
  18.     } 
  19.  
  20.     return (false); 

GetUnicodeCategory()方法調用InternalGetUnicodeCategory()方法,而且實際上相當快,但現在我們依次已經有了4個方法調用!以下這段代碼是由一位評論者提供的,可用于快速實現定制版本和JIT默認內聯:

  1. // whitespace detection method: very fast, a lot faster than Char.IsWhiteSpace 
  2. [MethodImpl(MethodImplOptions.AggressiveInlining)] // if it's not inlined then it will be slow!!! 
  3. public static bool isWhiteSpace(char ch) { 
  4.     // this is surprisingly faster than the equivalent if statement 
  5.     switch (ch) { 
  6.         case '\u0009'case '\u000A'case '\u000B'case '\u000C'case '\u000D'
  7.         case '\u0020'case '\u0085'case '\u00A0'case '\u1680'case '\u2000'
  8.         case '\u2001'case '\u2002'case '\u2003'case '\u2004'case '\u2005'
  9.         case '\u2006'case '\u2007'case '\u2008'case '\u2009'case '\u200A'
  10.         case '\u2028'case '\u2029'case '\u202F'case '\u205F'case '\u3000'
  11.             return true
  12.         default
  13.             return false
  14.     } 

刪除字符串的不同方法

我用各種不同的方法來實現刪除字符串中的所有空白。

分離合并法

這是我一直在用的一個非常簡單的方法。根據空格字符分離字符串,但不包括空項,然后將產生的碎片重新合并到一起。這方法聽上去有點傻乎乎的,而事實上,乍一看,很像是一個非常浪費的解決方式:

  1. public static string TrimAllWithSplitAndJoin(string str) { 
  2.     return string.Concat(str.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries)); 

LINQ

這是優雅地聲明式地實現這個過程的方法:

  1. public static string TrimAllWithLinq(string str) { 
  2.     return new string(str.Where(c => !isWhiteSpace(c)).ToArray()); 

正則表達式

正則表達式是非常強大的力量,任何程序員都應該意識到這一點。

 

  1. static Regex whitespace = new Regex(@"\s+", RegexOptions.Compiled); 
  2.  
  3. public static string TrimAllWithRegex(string str) { 
  4.     return whitespace.Replace(str, ""); 

字符數組原地轉換法

該方法將輸入的字符串轉換成字符數組,然后原地掃描字符串去除空白字符(不創建中間緩沖區或字符串)。***,經過“刪減”的數組會產生新的字符串。

  1. public static string TrimAllWithInplaceCharArray(string str) { 
  2.     var len = str.Length; 
  3.     var src = str.ToCharArray(); 
  4.     int dstIdx = 0
  5.     for (int i = 0; i < len; i++) { 
  6.         var ch = src[i]; 
  7.         if (!isWhiteSpace(ch)) 
  8.             src[dstIdx++] = ch; 
  9.     } 
  10.     return new string(src, 0, dstIdx); 

字符數組復制法

這種方法類似于字符數組原地轉換法,但它使用Array.Copy復制連續非空白“字符串”的同時跳過空格。***,它將創建一個適當尺寸的字符數組,并用相同的方式返回一個新的字符串。

  1. public static string TrimAllWithCharArrayCopy(string str) { 
  2.     var len = str.Length; 
  3.     var src = str.ToCharArray(); 
  4.     int srcIdx = 0, dstIdx = 0, count = 0
  5.     for (int i = 0; i < len; i++) { 
  6.         if (isWhiteSpace(src[i])) { 
  7.             count = i - srcIdx; 
  8.             Array.Copy(src, srcIdx, src, dstIdx, count); 
  9.             srcIdx += count + 1
  10.             dstIdx += count; 
  11.             len--; 
  12.         } 
  13.     } 
  14.     if (dstIdx < len) 
  15.         Array.Copy(src, srcIdx, src, dstIdx, len - dstIdx); 
  16.     return new string(src, 0, len); 

循環交換法

用代碼實現循環,并使用StringBuilder類,通過依靠StringBuilder的內在優化來創建新的字符串。為了避免任何其他因素對本實施產生干擾,不調用其他的方法,并且通過緩存到本地變量避免訪問類成員。***通過設置StringBuilder.Length將緩沖區調整到合適大小。

  1. // Code suggested by http://www.codeproject.com/Members/TheBasketcaseSoftware 
  2. public static string TrimAllWithLexerLoop(string s) { 
  3.     int length = s.Length; 
  4.     var buffer = new StringBuilder(s); 
  5.     var dstIdx = 0; 
  6.     for (int index = 0; index < s.Length; index++) { 
  7.         char ch = s[index]; 
  8.         switch (ch) { 
  9.             case '\u0020'case '\u00A0'case '\u1680'case '\u2000'case '\u2001'
  10.             case '\u2002'case '\u2003'case '\u2004'case '\u2005'case '\u2006'
  11.             case '\u2007'case '\u2008'case '\u2009'case '\u200A'case '\u202F'
  12.             case '\u205F'case '\u3000'case '\u2028'case '\u2029'case '\u0009'
  13.             case '\u000A'case '\u000B'case '\u000C'case '\u000D'case '\u0085'
  14.                 length--; 
  15.                 continue
  16.             default
  17.                 break
  18.         } 
  19.         buffer[dstIdx++] = ch; 
  20.     } 
  21.     buffer.Length = length; 
  22.     return buffer.ToString();; 

循環字符法

這種方法幾乎和前面的循環交換法相同,不過它采用if語句來調用isWhiteSpace(),而不是亂七八糟的switch伎倆 :)。

  1. public static string TrimAllWithLexerLoopCharIsWhitespce(string s) { 
  2.     int length = s.Length; 
  3.     var buffer = new StringBuilder(s); 
  4.     var dstIdx = 0
  5.     for (int index = 0; index < s.Length; index++) { 
  6.         char currentchar = s[index]; 
  7.         if (isWhiteSpace(currentchar)) 
  8.             length--; 
  9.         else 
  10.             buffer[dstIdx++] = currentchar; 
  11.     } 
  12.     buffer.Length = length; 
  13.     return buffer.ToString();; 

原地改變字符串法(不安全)

這種方法使用不安全的字符指針和指針運算來原地改變字符串。我不推薦這個方法,因為它打破了.NET框架在生產中的基本約定:字符串是不可變的。

 

  1. public static unsafe string TrimAllWithStringInplace(string str) { 
  2.     fixed (char* pfixed = str) { 
  3.         char* dst = pfixed; 
  4.         for (char* p = pfixed; *p != 0; p++) 
  5.             if (!isWhiteSpace(*p)) 
  6.                 *dst++ = *p; 
  7.  
  8.         /*// reset the string size 
  9.             * ONLY IT DIDN'T WORK! A GARBAGE COLLECTION ACCESS VIOLATION OCCURRED AFTER USING IT 
  10.             * SO I HAD TO RESORT TO RETURN A NEW STRING INSTEAD, WITH ONLY THE PERTINENT BYTES 
  11.             * IT WOULD BE A LOT FASTER IF IT DID WORK THOUGH... 
  12.         Int32 len = (Int32)(dst - pfixed); 
  13.         Int32* pi = (Int32*)pfixed; 
  14.         pi[-1] = len; 
  15.         pfixed[len] = '\0';*/ 
  16.         return new string(pfixed, 0, (int)(dst - pfixed)); 
  17.     } 

原地改變字符串法V2(不安全)

這種方法幾乎和前面那個相同,不過此處使用類似數組的指針訪問。我很好奇,不知道這兩種哪種存儲訪問會更快。

  1. public static unsafe string TrimAllWithStringInplaceV2(string str) { 
  2.     var len = str.Length; 
  3.     fixed (char* pStr = str) { 
  4.         int dstIdx = 0
  5.         for (int i = 0; i < len; i++) 
  6.             if (!isWhiteSpace(pStr[i])) 
  7.                 pStr[dstIdx++] = pStr[i]; 
  8.         // since the unsafe string length reset didn't work we need to resort to this slower compromise 
  9.         return new string(pStr, 0, dstIdx); 
  10.     } 

String.Replace(“”,“”)

這種實現方法很天真,由于它只替換空格字符,所以它不使用空白的正確定義,因此會遺漏很多其他的空格字符。雖然它應該算是本文中最快的方法,但功能不及其他。

但如果你只需要去掉真正的空格字符,那就很難用純.NET寫出勝過string.Replace的代碼。大多數字符串方法將回退到手動優化本地C ++代碼。而String.Replace本身將用comstring.cpp調用C ++方法:

  1. FCIMPL3(Object*, 
  2.     COMString::ReplaceString, 
  3.     StringObject* thisRefUNSAFE, 
  4.     StringObject* oldValueUNSAFE, 
  5.     StringObject* newValueUNSAFE) 

下面是基準測試套件方法:

 

  1. public static string TrimAllWithStringReplace(string str) { 
  2.     // This method is NOT functionaly equivalent to the others as it will only trim "spaces" 
  3.     // Whitespace comprises lots of other characters 
  4.     return str.Replace(" """); 

許可證

這篇文章,以及任何相關的源代碼和文件,依據The Code Project Open License (CPOL)的許可。

譯文鏈接:http://www.codeceo.com/article/donet-remove-whitespace-string.html
英文原文:Fastest method to remove all whitespace from Strings in .NET

 

責任編輯:王雪燕 來源: 碼農網
相關推薦

2015-08-13 10:42:49

.NET空白字符串

2020-09-07 13:08:36

String空白字符方式

2010-11-25 15:59:33

字符串.NET

2009-07-24 13:01:44

ASP.NET頁面跳轉

2025-05-21 04:00:00

JavaScript前端

2020-09-03 10:13:49

JavaScript字符串pad

2010-05-07 08:59:50

ASP.NET

2009-07-06 13:18:35

Servlet方法

2009-07-28 10:36:37

ASP.NET讀取Ex

2010-06-21 09:48:43

2013-07-15 11:00:18

提升WI-FI信號強度

2010-01-13 15:12:04

VB.NET字符串合并

2009-07-24 10:06:33

數據庫字符串ASP.NET

2024-04-01 08:41:39

字符串.NET

2020-10-16 18:35:53

JavaScript字符串正則表達式

2009-11-26 18:28:07

PHP函數trim()

2020-05-14 10:24:41

YAML配置字符串

2019-12-10 10:31:30

javascriptWeb前端開發

2021-05-18 09:08:18

字符串子串對象

2010-01-18 09:55:30

VB.NET刪除空白行
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人免费视频网站在线看 | 日日操操操 | 午夜影院在线观看免费 | 国产免费一区二区三区 | 国产综合av| 久国产视频| 99亚洲精品 | 日韩国产中文字幕 | 嫩草视频入口 | 欧美激情啪啪 | 亚洲一区二区三区免费在线观看 | 欧美日韩一区在线 | 亚洲成人av在线播放 | 在线免费观看黄色av | 免费国产黄| 国产精品一区在线观看 | 欧美中文在线 | 国产精品网址 | 久久国产一区 | 婷婷毛片 | 日韩av啪啪网站大全免费观看 | 欧美xxxx黑人又粗又长 | 欧美又大粗又爽又黄大片视频 | 欧美高清成人 | 久久黄色 | 亚洲国产精品久久久 | 国产欧美精品一区二区 | 色爱区综合 | 久热免费 | 午夜理伦三级理论三级在线观看 | 天天操,夜夜爽 | 人人鲁人人莫人人爱精品 | 秋霞在线一区二区 | 老子午夜影院 | 一区二区中文 | 欧美乱人伦视频 | 日本不卡免费新一二三区 | 一级在线| 亚洲高清在线视频 | 欧美日韩久久精品 | 久草资源在线视频 |