2012-02-20 11 views
93

स्ट्रिंग में ReplaceAt() नहीं है, और मैं एक सभ्य कार्य करने के तरीके पर थोड़ा सा झुका रहा हूं जो मुझे चाहिए। मुझे लगता है कि सीपीयू लागत बहुत अधिक है, लेकिन स्ट्रिंग आकार छोटे हैं तो यह की तरह सब ठीक कुछस्ट्रिंग में दिए गए इंडेक्स पर एक char को बदलना?

+4

क्या आपके पास 'है' के बजाय 'नहीं है' का मतलब नहीं था? :) – Abbas

उत्तर

166

उपयोग एक StringBuilder:

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

आह, स्ट्रिंगबिल्डर साफ है – Jason94

+5

@ जेसन 94, मुझे यकीन नहीं है कि यह जॉन के जवाब के रूप में ToCharArray का उपयोग करने से अधिक कुशल है, आपको यह देखने के लिए परीक्षण करना चाहिए कि कौन सा तेज़ है। –

+13

मैंने 100k पुनरावृत्तियों पर थोड़ा बेंचमार्क के साथ प्रयास किया, ToCharArray कम से कम 2 गुना तेज है। –

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

स्वीकार्य उत्तर के तहत टिप्पणियां इंगित करती हैं कि यह दृष्टिकोण तेज़ी से दोगुना है। – 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 

यह किसी तरह कि केवल एक एकल डेटा की प्रतिलिपि आवश्यक के बारे में सोचना अच्छा होगा यहां दोनों की बजाय बनाया जाना है, लेकिन मुझे ऐसा करने का कोई तरीका नहीं है। यह संभव है कि यह करना होगा:

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() विधि स्ट्रिंगबिल्डर विधि से तेज़ है। एक और संभावित सुधार: इनपुट करें। गणना करें> सूचकांक -1 और अनुक्रमणिका> = 0 अन्यथा जब आप वर्ण [अनुक्रमणिका] या निर्माता [अनुक्रमणिका] करते हैं तो आपको अपवाद मिलेगा। –

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 पर वर्ण। – EventHorizon

+0

स्ट्रिंग त्रुटि = त्रुटि.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 शैली संस्करण है

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

अंत मैं नेट फ्रेमवर्क 2 का उपयोग करने के लिए आवश्यक है, तो मैं एक StringBuilder वर्ग भिन्न रूप का उपयोग हालांकि।

+0

क्या यह लंबी स्ट्रिंग के लिए धीमा नहीं होगा? 'स्ट्रिंगबिल्डर 'या' ToCharArray' समाधान 'के बजाय ऐसा क्यों करें? यह * स्ट्रिंग की एक कम प्रति हो सकती है ('स्ट्रिंगबिल्डर 'की तुलना में), लेकिन मुझे संदेह है कि आंतरिक रूप से बहुत कुछ होता है। – 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

बेशक, यह 'स्ट्रिंग' के अर्थशास्त्र का उल्लंघन करता है - इस ऑब्जेक्ट के किसी भी अन्य संदर्भ को प्रभावित करता है, जो 'स्ट्रिंग' ऑब्जेक्ट्स * अपरिवर्तनीय * दस्तावेज को रद्द/विरोधाभासी करता है। ऐसा करने के लिए, एक अंतर्निहित कक्षा में, अत्यधिक संदिग्ध (मजबूत कोड गंध) है। उस पर एक विशाल चेतावनी टिप्पणी की आवश्यकता है। व्यक्तिगत रूप से, मैं ** ** नहीं करूँगा। अगर किसी को * mutable * स्ट्रिंग की आवश्यकता होती है, तो एक उचित वर्ग, subclassing या 'char [] 'लपेटें। – ToolmakerSteve

संबंधित मुद्दे