2012-02-20 59 views
93

字符串沒有ReplaceAt(),我正在翻倒一點如何做一個體面的功能,做我所需要的。我想的CPU成本高,但串尺寸小,所以這一切都OK替換字符串中給定索引處的字符?

+4

難道你不是指'沒有'而是'有'嗎? :) – Abbas 2012-02-20 19:27:35

回答

166

使用StringBuilder

StringBuilder sb = new StringBuilder(theString); 
sb[index] = newChar; 
theString = sb.ToString(); 
+3

啊,Stringbuilder是整潔的 – Jason94 2012-02-20 20:04:20

+5

@ Jason94,我不確定這比使用ToCharArray更有效,因爲在Jon的回答中,您應該運行測試以查看哪一個更快。 – 2012-02-20 20:18:34

+13

我嘗試了一個100k迭代的基準測試,ToCharArray至少快了2倍。 – 2013-05-13 08:55:42

19
string s = "ihj"; 
char[] array = s.ToCharArray(); 
array[1] = 'p'; 
s = new string(array); 
+1

根據接受的答案評論表明,這種方法是兩倍的速度。 – Dejan 2015-11-02 15:50:30

69

簡單的做法是這樣的:

public static string ReplaceAt(this string input, int index, char newChar) 
{ 
    if (input == null) 
    { 
     throw new ArgumentNullException("input"); 
    } 
    char[] chars = input.ToCharArray(); 
    chars[index] = newChar; 
    return new string(chars); 
} 

現在這是一個擴展方法,所以你可以使用:

var foo = "hello".ReplaceAt(2, 'x'); 
Console.WriteLine(foo); // hexlo 

想一些辦法,只有需要的數據的副本這將是很好而不是兩個在這裏,但我不知道有什麼辦法做到這一點。這是可能,這將做到這一點:

public static string ReplaceAt(this string input, int index, char newChar) 
{ 
    if (input == null) 
    { 
     throw new ArgumentNullException("input"); 
    } 
    StringBuilder builder = new StringBuilder(input); 
    builder[index] = newChar; 
    return builder.ToString(); 
} 

...我懷疑這完全取決於哪個版本您正在使用的框架。

+2

+1作爲擴展方法。正如接受的答案的評論以及其他答案中所述,ToCharArray()方法比StringBuilder方法更快。 還有一種可能的改進:檢查input.Count> index-1 && index> = 0,否則當你執行chars [index]或builder [index]時你會得到一個異常。 – 2016-07-07 09:08:39

3

字符串是不可變對象,所以你不能替換字符串在給定的角色。 你可以做的是你可以用給定的字符替換來創建一個新的字符串。

但是,如果你要創建一個新的字符串,爲什麼不使用StringBuilder:

string s = "abc"; 
StringBuilder sb = new StringBuilder(s); 
sb[1] = 'x'; 
string newS = sb.ToString(); 

//newS = "axc"; 
-2
public string ReplaceChar(string sourceString, char newChar, int charIndex) 
    { 
     try 
     { 
      // if the sourceString exists 
      if (!String.IsNullOrEmpty(sourceString)) 
      { 
       // verify the lenght is in range 
       if (charIndex < sourceString.Length) 
       { 
        // Get the oldChar 
        char oldChar = sourceString[charIndex]; 

        // Replace out the char ***WARNING - THIS CODE IS WRONG - it replaces ALL occurrences of oldChar in string!!!*** 
        sourceString.Replace(oldChar, newChar); 
       } 
      } 
     } 
     catch (Exception error) 
     { 
      // for debugging only 
      string err = error.ToString(); 
     } 

     // return value 
     return sourceString; 
    } 
+1

sourceString.Replace(oldChar,newChar)替換字符串中的所有oldChar,而不僅僅是charIndex處的字符。 – EventHorizon 2013-06-26 09:53:12

+0

string err = error.ToString();爲什麼? – 2015-01-23 11:23:04

4

我突然需要做這個任務,發現了這個話題。 所以,這是我的LINQ風格的變體:

public static class Extensions 
{ 
    public static string ReplaceAt(this string value, int index, char newchar) 
    { 
     if (value.Length <= index) 
      return value; 
     else 
      return string.Concat(value.Select((c, i) => i == index ? newchar : c)); 
    } 
} 

,然後,例如:

string instr = "Replace$dollar"; 
string outstr = instr.ReplaceAt(7, ' '); 

在我需要利用.Net框架2月底,所以我用一個StringBuilder類變種雖然。

+0

這是不是很慢,對於一個長串?爲什麼要這樣做,而不是'StringBuilder'或'ToCharArray'解決方案?它*可能是字符串的一個副本(與'StringBuilder'相比),但我懷疑內部發生了很多事情。 – ToolmakerSteve 2017-04-08 20:47:57

0

如果你的項目(.csproj的)允許不安全的代碼可能,這是更快的解決方案:

namespace System 
{ 
    public static class StringExt 
    { 
    public static unsafe void ReplaceAt(this string source, int index, char value) 
    { 
     if (source == null) 
      throw new ArgumentNullException("source"); 

     if (index < 0 || index >= source.Length) 
      throw new IndexOutOfRangeException("invalid index value"); 

     fixed (char* ptr = source) 
     { 
      ptr[index] = value; 
     } 
    } 
    } 
} 

你可以使用它作爲字符串對象的擴展方法。

+1

當然,這違反了'string'的語義 - 影響對這個對象的任何其他引用,取消/違反'string'對象是* immutable *的文檔。這樣做,對於一個內置的類,是非常可疑的(強烈的代碼味道)。需要一個巨大的警告評論在它上面。就我個人而言,我不會**這樣做。如果有人需要一個* mutable *字符串,然後創建一個適當的類,繼承或包裝一個'char []'。 – ToolmakerSteve 2017-04-08 20:35:51

相關問題