批量字符串替换程序

        很多时候我们需要用到字符串替换程序,比如插入数据库时需要将'替换成''。当只有少数待换字符串时用String.Replace性能很高,但因为其复杂度是O(n),当待换字符串很多的时候,String.Replace的性能就降下来了。前些天写了几个程序,用于批量替换字符串。

问题:批量替换字符串。定义字符串对PairString{OldValue,NewValue}。
                                OldValue<------>NewValue 
            称---->为右过滤,简称过滤。<----为左过滤,或反过滤。
            给定字符串S,一个PairString数组,用PairString数组过滤S(左、右可设置)。

程序实现:

(1)PairString

 1    public struct PairString
 2    {
 3        public string OldValue;
 4        public string NewValue;
 5        public bool IsRightFilter;
 6        public bool IsLeftFilter;
 7
 8        public PairString(string oldValue, string newValue)
 9        {
10            OldValue=oldValue;
11            NewValue=newValue;
12            IsRightFilter=true;
13            IsLeftFilter=true;
14        }

15
16        public PairString(string oldValue, string newValue, bool isRightFilter, bool isLeftFilter)
17        {
18            OldValue=oldValue;
19            NewValue=newValue;
20            IsRightFilter=isRightFilter;
21            IsLeftFilter=isLeftFilter;
22        }

23    }


(2)采用Replace实现

 1    public class StringFilter
 2    {
 3        private PairString[] _filterSet=null;
 4
 5        public PairString[] FilterSet
 6        {
 7            get
 8            {
 9                return _filterSet;
10            }

11            set
12            {
13                _filterSet=value;
14            }

15        }

16
17
18        public StringFilter()
19        {
20        }

21
22
23        public virtual  string Filter(string input)
24        {
25            foreach (PairString p in FilterSet)
26            {
27                if(p.IsRightFilter==true) input=input.Replace(p.OldValue,p.NewValue);
28            }

29            return input;
30        }

31
32        public virtual string AntiFilter(string input)
33        {
34            foreach (PairString p in FilterSet)
35            {
36                if(p.IsLeftFilter==true) input=input.Replace(p.NewValue,p.OldValue);
37            }

38            return input;
39        }

40    }

(3)批量替换。我最先采用Hashtable实现,测试结果发现性能比较低,然后就直接改用数组实现,写一个hash函数,将待换字符串hash到数组。flexIndex是松弛系数。

  1    public class StringBatchFilter:StringFilter
  2    {
  3        private int width=0;
  4        const int flexIndex = 10;
  5
  6        private object[] _rightArray;
  7        private object[] _leftArray;
  8
  9        public object[] RightArray
 10        {
 11            get
 12            {
 13                return _rightArray;
 14            }

 15            set
 16            {
 17                _rightArray = value;
 18            }

 19        }

 20
 21        public object[] LeftArray
 22        {
 23            get
 24            {
 25                return _leftArray;
 26            }

 27            set
 28            {
 29                _leftArray = value;
 30            }

 31        }

 32
 33        public StringBatchFilter()
 34        {
 35        }

 36
 37        public void Init()
 38        {
 39            width=flexIndex*FilterSet.Length;
 40            RightArray = new object[width];
 41            LeftArray = new object[width];
 42
 43            foreach (PairString p in FilterSet)
 44            {
 45                if(p.IsRightFilter==true)
 46                {
 47                    if(RightArray[p.OldValue[0]%width]==null)
 48                    {
 49                        RightArray[p.OldValue[0]%width]=new ArrayList();
 50                    }

 51                    ((ArrayList)RightArray[p.OldValue[0]%width]).Add(p);
 52
 53                }

 54
 55                if(p.IsLeftFilter==true)
 56                {
 57                    if(LeftArray[p.NewValue[0]%width]==null)
 58                    {
 59                        LeftArray[p.NewValue[0]%width]=new ArrayList();
 60                    }

 61                    else
 62                    {
 63                        ((ArrayList)LeftArray[p.NewValue[0]%width]).Add(p);
 64                    }

 65                }

 66            }

 67        }

 68
 69        public override string Filter(string input)
 70        {
 71            StringBuilder sb = new StringBuilder((int)(input.Length*1.2));
 72
 73            for (int i=0; i< input.Length; )
 74            {
 75                int m = input[i]%width;
 76                ArrayList l = (ArrayList)RightArray[m];
 77                if(l!=null)
 78                {
 79                    for(int j=0;j<l.Count;j++)
 80                    {
 81                        PairString p = (PairString)l[j];
 82                        if(((i+p.OldValue.Length)<input.Length))
 83                        {
 84                            if(input.Substring(i,p.OldValue.Length)==p.OldValue)
 85                            {
 86                                sb.Append(p.NewValue);
 87                                i+=p.OldValue.Length;
 88                                goto label;
 89                            }

 90                        }

 91                    }

 92                    sb.Append(input[i]);
 93                    i++;
 94                label:
 95                    ;
 96                }

 97                else
 98                {
 99                    sb.Append(input[i]);
100                    i++;
101                }

102            }

103            return sb.ToString();
104        }

105
106        public override string AntiFilter(string input)
107        {
108            StringBuilder sb = new StringBuilder((int)(input.Length*1.2));
109
110            for (int i=0; i< input.Length; )
111            {
112                int m = input[i]%width;
113                ArrayList l = (ArrayList)LeftArray[m];
114                if(l!=null)
115                {
116                    for(int j=0;j<l.Count;j++)
117                    {
118                        PairString p = (PairString)l[j];
119                        if(((i+p.NewValue.Length)<input.Length))
120                        {
121                            if(input.Substring(i,p.NewValue.Length)==p.NewValue)
122                            {
123                                sb.Append(p.OldValue);
124                                i+=p.NewValue.Length;
125                                goto label;
126                            }

127                        }

128                    }

129                    sb.Append(input[i]);
130                    i++;
131                label:
132                    ;
133                }

134                else
135                {
136                    sb.Append(input[i]);
137                    i++;
138                }

139            }

140            return sb.ToString();
141        }

142    }

(4)例子

 1    StringBatchFilter sk = new StringBatchFilter();
 2
 3    PairString[] p =
 4     {
 5         new PairString(Environment.NewLine,"<br>"),
 6         new PairString("    ","&nbsp;&nbsp;&nbsp;&nbsp;"),
 7         new PairString("'","''",true,false)
 8     }
;
 9    sk.Init();
10    sk.FilterSet = p;
11    sk.Filter();

一般来说,如果待换字符串在10个以下,使用Replace性能较高。10个以上的,批量替换的优势就体现出来了。
posted @ 2005-08-15 10:32  xiaotie  阅读(3799)  评论(4编辑  收藏  举报