2012-02-20 40 views

Trả lời

166

Sử dụng một StringBuilder:

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

ah, Stringbuilder gọn gàng – Jason94

+5

@ Jason94, tôi không chắc điều này hiệu quả hơn việc sử dụng ToCharArray như trong câu trả lời của Jon, bạn nên chạy thử nghiệm để xem cái nào nhanh hơn. –

+13

Tôi đã thử với một chút điểm chuẩn về các lần lặp 100k, ToCharArray nhanh hơn ít nhất 2 lần. –

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

Nhận xét theo câu trả lời được chấp nhận cho biết rằng cách tiếp cận này nhanh gấp hai lần. – Dejan

69

Các đơn giản nhất cách tiếp cận sẽ là một cái gì đó như:

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

này bây giờ là một phương pháp mở rộng, do đó bạn có thể sử dụng:

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

Nó sẽ được tốt đẹp để nghĩ về một số cách mà chỉ cần một đơn bản sao của dữ liệu được thực hiện hơn là hai ở đây, nhưng tôi không chắc chắn về bất kỳ cách nào để làm điều đó. Đó là thể rằng điều này sẽ làm điều đó:

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

... tôi nghi ngờ nó hoàn toàn phụ thuộc vào phiên bản của khuôn khổ bạn đang sử dụng.

+2

+1 để biến nó thành một phương thức mở rộng. Như đã đề cập trong phần bình luận của câu trả lời được chấp nhận và cũng trong các câu trả lời khác, phương thức ToCharArray() nhanh hơn phương thức StringBuilder. Một cải tiến có thể có hơn: kiểm tra xem input.Count> index-1 && index> = 0 nếu không bạn sẽ nhận được một ngoại lệ khi bạn thực hiện chars [index] hoặc builder [index]. –

3

Strings là đối tượng bất biến, vì vậy bạn không thể thay thế một nhân vật được đưa ra trong chuỗi. Những gì bạn có thể làm là bạn có thể tạo một chuỗi mới với ký tự đã cho thay thế.

Nhưng nếu bạn là để tạo ra một chuỗi mới, tại sao không sử dụng một 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) thay thế tất cả các lần xuất hiện của oldChar trong chuỗi, không chỉ là ký tự tại charIndex. – EventHorizon

+0

string err = error.ToString(); tại sao? –

4

tôi đột nhiên cần thiết để làm nhiệm vụ này và tìm thấy chủ đề này. Vì vậy, đây là của tôi biến LINQ-style:

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

và sau đó, ví dụ:

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

Trong khi kết thúc tôi cần phải sử dụng Net Framework 2, vì vậy tôi sử dụng một biến thể StringBuilder lớp Tuy nhiên.

+0

Nó sẽ không được làm chậm, cho một chuỗi dài? Tại sao điều này, thay vì 'StringBuilder' hoặc' ToCharArray' giải pháp? Nó * có thể * là một bản sao ít hơn của chuỗi (so với 'StringBuilder'), nhưng tôi nghi ngờ rất nhiều xảy ra trong nội bộ. – ToolmakerSteve

0

Nếu dự án của bạn (csproj) cho phép mã không an toàn có lẽ đây là giải pháp nhanh hơn:

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

Bạn có thể sử dụng nó như phương pháp mở rộng của Chuỗi đối tượng.

+1

Tất nhiên, điều này vi phạm ngữ nghĩa của 'chuỗi' - ảnh hưởng đến bất kỳ tham chiếu nào khác đối tượng này, vô hiệu hóa/mâu thuẫn tài liệu mà các đối tượng' chuỗi' là * không thay đổi *. Làm như vậy, với một lớp được xây dựng trong, là rất đáng ngờ (mùi mã mạnh). Cần một chú thích WARNING khổng lồ tát vào nó. Cá nhân, tôi sẽ không ** làm điều này. Nếu ai đó cần một chuỗi * mutable *, sau đó tạo một lớp thích hợp, phân lớp hoặc gói một 'char []'. – ToolmakerSteve

Các vấn đề liên quan