2012-02-13 13 views
8

मुझे आश्चर्य हुआ कि स्ट्रिंग वर्णों को प्रतिस्थापित करने का सबसे आसान तरीका क्या है जिसे बाद में बदला जाना चाहिए।खराब वर्णों के साथ स्ट्रिंग के खराब वर्णों को प्रतिस्थापित करना

उदाहरण के लिए:

var str = "[Hello World]"; 
//enclose all occurences of [ and ] with brackets[] 
str = str.Replace("[","[[]").Replace("]","[]]"); 
  • वांछित परिणाम: [[]Hello World[]]
  • वास्तविक परिणाम: [[[]]Hello World[]]

कारण स्पष्ट रूप से है दूसरे को पहले से ही संशोधित स्ट्रिंग पर बदलें।

तो "खराब" वर्णों वाले वर्णों के साथ "खराब" वर्णों के सभी अवसरों को कैसे प्रतिस्थापित करें?


सभी तरीकों में से एक त्वरित माप से पता चला कि StringBuilder लिए सबसे कारगर तरीका है।

190kb फ़ाइल (मिलीसेकेंड में सभी)

regexTime   40.5065 
    replaceTime   20.8891 
    stringBuilderTime 6.9776 

7MB फ़ाइल

regexTime   1209.3529   
    replaceTime   403.3985 
    stringBuilderTime 175.2583 

वैसे, जॉन गया था से सीधे StringBuilder दृष्टिकोण दो बार के रूपके रूप में तेज़से से दृष्टिकोण।

मैं इसे से बाहर एक विस्तार कर दिया है:

public static String EncloseChars(this string input, char[] charsToEnclose, String leftSide, String rightSide) { 
    if (charsToEnclose == null || leftSide == null || rightSide == null) 
     throw new ArgumentException("Invalid arguments for EncloseChars", charsToEnclose == null ? "charsToEnclose" : leftSide == null ? "leftSide" : "rightSide"); 
    Array.Sort(charsToEnclose); 
    StringBuilder sb = new StringBuilder(); 
    foreach (char c in input) { 
     if (Array.BinarySearch(charsToEnclose, c) > -1) 
      sb.Append(leftSide).Append(c).Append(rightSide); 
     else 
      sb.Append(c); 
    } 
    return sb.ToString(); 
} 

"[Hello World]".EncloseChars(new char[]{'[', ']'},"[","]"); 
+3

+1 अच्छी तरह से मापा गया, टिम करने के लिए एक सहायक कार्य किया। –

उत्तर

5

यहां एक बहुत ही uncool ऐसा करने का तरीका है। लेकिन यह मूर्खतापूर्ण के करीब होने का लाभ है, मुझे लगता है, और रेगेक्स का उपयोग नहीं कर रहा है (यदि आप रेगेक्स का उपयोग नहीं करेंगे)।

Regex.Replace("[Hello World]", @"[\[\]]", "[$0]"); 

यूनिट परीक्षण यह:

StringBuilder sb = new StringBuilder(); 
foreach (char c in str.ToCharArray()) { 
    if (c == '[' || c == ']') { 
     sb.Append('[' + c + ']'); 
    } 
    else { 
     sb.Append(c); 
    } 
} 
string result = sb.ToString(); 
+0

धन्यवाद। अक्सर uncool रास्ता सबसे अच्छा/सबसे तेज है। किसी एक्सटेंशन विधि में छिपी हुई कोई समस्या नहीं;) –

4

के बारे में क्या:

str = str.Replace("[", "$1[$2") 
     .Replace("]", "$1]$2") 
     .Replace("$1", "[") 
     .Replace("$2", "]"); 
+2

मध्यस्थों के रूप में मॉनीटर मूल्यों का उपयोग करके अच्छा विचार। – Oded

+4

लेकिन आपको यह जांचना चाहिए कि स्ट्रिंग में पहले से ही इन मॉनीटर मान शामिल नहीं हैं, या फिर ऐसा ही होता है। उदाहरण: 'हैलो [$ 1] ' – Oliver

+0

मॉनिटर वैल्यू को प्रतिस्थापित करने के लिए संपादन + वास्तविक वर्ण मानों को बदलने से पहले वास्तविक वर्ण ओलिवर की समस्या को ठीक कर सकते हैं (यद्यपि दीवारों और सीढ़ियों के प्रकार में), लेकिन पठनीयता की कीमत पर , मुझे लगता है। –

1

कैसे के बारे में:

char[] replacedChars = str.SelectMany(ch => 
            (ch == '[' ? new char[] {'[', '[', ']'} : 
            (ch == ']' ? new char[] {'[', ']', ']'} : 
            new char[] {ch}))).ToArray(); 
string replaced = new string(replacedChars); 

ध्यान दें कि यह कई छोरों मुद्दे से बचा जाता है लेकिन कम से कम कई सरणी बनाता है क्योंकि इनपुट स्ट्रिंग में वर्ण हैं इसलिए यह प्रदर्शन के संदर्भ में इष्टतम नहीं हो सकता है।

+0

+1 LINQ का उपयोग बनाएं। बहुत प्रदर्शन नहीं ... :) – sehe

3
इस सुरुचिपूर्ण नियमित अभिव्यक्ति दृष्टिकोण के बारे में

क्या?

[TestMethod] 
public void UnitTestThat() 
{ 
    Assert.AreEqual(@"[[]Hello World[]]", Regex.Replace("[Hello World]", @"[\[\]]", "[$0]")); 
} 

परीक्षा उत्तीर्ण की


संपादित @JohnMcGrant

यहाँ अपने कोड है, जो है, वैसे, वास्तव में इसके बाद के संस्करण regex के रूप में ही व्यवहार का एक थोड़ा कम अक्षम संस्करण है:

string result = input.Aggregate(new StringBuilder(), (a, c) => 
    -1 != "[]".IndexOf(c) ? a.AppendFormat("[{0}]", c) : a.Append(c)).ToString(); 
+0

यह मानने के लिए शायद सुरक्षित है कि ऐसा नहीं होगा, लेकिन अगर ब्रैकेट किए गए टेक्स्ट में वैध रूप से ब्रैकेट हो सकते हैं, तो शायद किसी भी तरह से बच निकले। क्या वह रेगेक्स तोड़ नहीं सकता? –

+0

@ जॉन एमजींट: नहीं, क्योंकि इसका मतलब है कि आवश्यकताओं में बदलाव आया है। क्या होगा अगर सवाल अलग था? क्या वह जवाब तोड़ देगा? नहीं। – sehe

+0

@ जॉनमैंट के संस्करण के आधार पर जोड़ा गया वैकल्पिक दृष्टिकोण। मुझे लगता है कि रेगेक्स अभी भी सबसे अच्छा तरीका है :) – sehe

1
StringBuilder result = new StringBuilder(); 

    foreach (Char singleCharacter in str) 
    { 
     result.Append(singleCharacter.Equals('[') ? "[[]" : singleCharacter.Equals(']') ? "[]]" : singleCharacter.ToString()); 
    } 

    str = result.ToString(); 
0

मुझे एक ही समस्या थी, इसलिए मैंने केवल

protected string ReplaceUsingDictionary(string subject, Dictionary<string,string> pairs) 
    { 
     StringBuilder sb = new StringBuilder(subject); 

     sb.Replace("{", "{{").Replace("}", "}}"); 

     int i=0; 
     foreach (string key in pairs.Keys.ToArray()) 
     { 
      sb.Replace(
       key.Replace("{", "{{").Replace("}", "}}"), 
       "{" + i + "}" 
      ); 

      i++; 
     } 

     return string.Format(sb.ToString(), pairs.Values.ToArray()); 
    } 

// usage 
Dictionary<string, string> replacements = new Dictionary<string, string>(); 
replacements["["] = "[[]"; 
replacements["]"] = "[]]"; 

string mystr = ReplaceWithDictionary("[HelloWorld]", replacements); // returns [[]HelloWorld[]] 
संबंधित मुद्दे