2010-01-18 133 views
1

我想要一個能夠這樣工作的有效方法如何在字符串的一個子部分上執行字符串替換?

編輯:對不起,我沒有把我以前試過的東西。我現在更新了這個例子。

// Method signature, Only replaces first instance or how many are specified in max 
public int MyReplace(ref string source,string org, string replace, int start, int max) 
{ 
    int ret = 0; 
    int len = replace.Length; 
    int olen = org.Length; 
    for(int i = 0; i < max; i++) 
    { 
      // Find the next instance of the search string 
      int x = source.IndexOf(org, ret + olen); 
      if(x > ret) 
      ret = x; 
      else 
      break; 

     // Insert the replacement 
     source = source.Insert(x, replace); 
     // And remove the original 
     source = source.Remove(x + len, olen); // removes original string 
    } 
    return ret; 
} 

string source = "The cat can fly but only if he is the cat in the hat"; 
int i = MyReplace(ref source,"cat", "giraffe", 8, 1); 

// Results in the string "The cat can fly but only if he is the giraffe in the hat" 
// i contains the index of the first letter of "giraffe" in the new string 

我問的唯一原因是因爲我實現我想像越來越慢用替代了1000個。

回答

10

如何:

public static int MyReplace(ref string source, 
    string org, string replace, int start, int max) 
{ 
    if (start < 0) throw new System.ArgumentOutOfRangeException("start"); 
    if (max <= 0) return 0; 
    start = source.IndexOf(org, start); 
    if (start < 0) return 0; 
    StringBuilder sb = new StringBuilder(source, 0, start, source.Length); 
    int found = 0; 
    while (max-- > 0) { 
     int index = source.IndexOf(org, start); 
     if (index < 0) break; 
     sb.Append(source, start, index - start).Append(replace); 
     start = index + org.Length; 
     found++; 
    } 
    sb.Append(source, start, source.Length - start); 
    source = sb.ToString(); 
    return found; 
} 

它使用StringBuilder避免大量的中間string S的;我沒有嚴格測試,但它似乎工作。當沒有匹配時,它也試圖避免額外的string

1

開始,嘗試這樣的事情:

int count = 0; 
Regex.Replace(source, Regex.Escape(literal), (match) => 
{ 
    return (count++ > something) ? "new value" : match.Value; 
}); 
0

僅替換第一場比賽:

private string ReplaceFirst(string source, string oldString, string newString) 
    { 
     var index = source.IndexOf(oldString); 
     var begin = source.Substring(0, index); 
     var end = source.Substring(index + oldString.Length); 
     return begin + newString + end; 
    } 
0

你有一個錯誤你會錯過的項目,以取代如果是在開始。

更改這些行;

int ret = start; // instead of zero, or you ignore the start parameter 

    // Find the next instance of the search string 
    // Do not skip olen for the first search! 
    int x = i == 0 ? source.IndexOf(org, ret) : source.IndexOf(org, ret + olen); 

另外你的日常工作會在我的機器上替換一秒鐘。你確定這將是一個瓶頸?

剛剛發現如果用較小的文本替換較大的文本,您的代碼也有問題。

0

如果您有四次替換,並且一次替換速度提高了10%(與發佈的原始代碼相比更快),此代碼速度提高100%。它使用指定的起始參數並在用較小的文本替換較大的文本時起作用。

Mark Gravells解決方案是(沒有違規;-)比原始代碼慢60%,它也返回另一個值。

// Method signature, Only replaces first instance or how many are specified in max 
    public static int MyReplace(ref string source, string org, string replace, int start, int max) 
    { 
     var ret = 0; 
     int x = start; 
     int reps = 0; 
     int l = source.Length; 
     int lastIdx = 0; 
     string repstring = ""; 

     while (x < l) 
     { 
      if ((source[x] == org[0]) && (reps < max) && (x >= start)) 
      { 
       bool match = true; 
       for (int y = 1; y < org.Length; y++) 
       { 
        if (source[x + y] != org[y]) 
        { 
         match = false; 
         break; 
        } 
       } 
       if (match) 
       { 
        repstring += source.Substring(lastIdx, x - lastIdx) + replace; 
        ret = x; 
        x += org.Length - 1; 
        reps++; 
        lastIdx = x + 1; 
        // Done? 
        if (reps == max) 
        { 
         source = repstring + source.Substring(lastIdx); 
         return ret; 
        } 
       } 
      } 
      x++; 
     } 

     if (ret > 0) 
     { 
      source = repstring + source.Substring(lastIdx); 
     } 

     return ret; 
    } 
相關問題