2012-02-20 4 views
93

문자열에 ReplaceAt()이 없으며 필자가 필요로하는 적절한 기능을 만드는 방법에 대해 약간 논란이있다. 이렇게하면 이제 확장 방법이다문자열에서 주어진 색인의 문자를 교체 하시겠습니까?

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

: 저는 CPU 비용이 높은 가정이지만 같은 모든 확인

+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

허용되는 대답 아래의 주석은이 접근법이 두 배 빠름을 나타냅니다. – Dejan

69

간단한 방법이 될 것이다 뭔가 그래서 문자열 크기가 작은 사용할 수 있습니다

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인지 확인하십시오. 그렇지 않으면 char [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

합니다. 다음

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 스타일의 변형입니다 내가 닷넷 프레임 워크 2를 사용하는 데 필요한 결국

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

, 그래서 StringBuilder 수준의 변형을 사용하여 그래도.

+0

긴 문자열의 경우 속도가 느리지 않습니까? 'StringBuilder' 또는'ToCharArray' 솔루션보다는 왜 이렇게할까요? StringBuilder와 비교해 볼 때 문자열의 복사본이 하나 더 적지 만 내부적으로는 많이 발생한다고 생각됩니다. – 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

관련 문제