2012-02-20 19 views
93

文字列にはReplaceAt()が含まれていません。私は、必要な機能を実行するためのちょっとした機能を少しぶつけています。私は、CPUのコストが高いと仮定しますが、最も簡単なアプローチのようなものになるだろう、それはすべてOK文字列内の指定されたインデックスの文字を置き換える?

+4

「持っていない」の代わりに「持っていない」という意味ではありませんか? :) – Abbas

答えて

166

StringBuilderを使用します。

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

ああ、Stringbuilderはきちんとしています – Jason94

+5

@ Jason94、これはJonの答えのようにToCharArrayを使うよりも効率的だとは思いますが、テストを実行してどちらが速いのかを確認する必要があります。 –

+13

私は100k回の反復で少しのベンチマークを試みましたが、ToCharArrayは少なくとも2回速かったです。 –

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

受け入れられた答えの下のコメントは、このアプローチが2倍の速さであることを示しています。拡張方法にするためには – Dejan

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 

それだけでデータの単一コピーを必要ないくつかの方法を考えていいだろうここでは2人ではなく作られることになっていますが、私はそれを行う方法についてはわかりません。これはそれを行うだろうと可能性です:

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]を実行したときに例外が発生します。 –

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)は、charIndexの文字だけでなく、文字列内のoldCharのすべてを置き換えます。 – EventHorizon

+0

string err = error.ToString();どうして? –

4

を。私は.NET Frameworkの2を利用するために必要な最終的には

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

ので、私はStringBuilderクラスのバリアントを使用します。たとえば、

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)); 
    } 
} 

、その後: だから、これは私のLINQスタイルの変異体でありますしかし、。

+0

長い文字列の場合、これは遅くならないでしょうか? 'StringBuilder'や' ToCharArray'ソリューションではなく、なぜこれを行うのですか? StringBuilderと比較して文字列のコピーが1つ少ないかもしれませんが、私は内部的に多くのことが起こると思います。 – ToolmakerSteve

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 *であるという文書を無効化/矛盾させます。これを組み込みクラスに組み込むことは、非常に疑わしい(強いコードの匂い)。それに打たれた巨大なWARNINGコメントが必要です。個人的には、私はこれをしません**。誰かが*変更可能な文字列を必要とする場合は、適切なクラスを作成し、 'char []'をサブクラス化するか、またはラップします。 – ToolmakerSteve

関連する問題