2010-01-18 134 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; 
    } 
相关问题