основной принцип работы твой, регулярка там используется только для удаления куска который обработали ибо лень уже было доделывать/ кусок с регуляркой можно заменить на: //string rep = Convert.ToString(rx.Match(message)); message = message.Replace(random, word);
он вообще-то несколько другой способ описывал. с введением кучей дополнительных переменных и обработкой строки "через Ж"
ув. бориска, не шарите - марш на выход. в том классе "regEx" который Вы так нахваливаете объявляется гораздо больше переменных (не говоря уже о времени на создание объекта (а это самая затратная по времени процедура. хотя вряд ли Вам это известно)), которые Вам для выполнения простейшей (!!!) задачи просто не нужны. расход памяти ГОРАЗДО выше, чем при объявлении 2 (двух) переменных
Вот моя реализация на C#, похожая на то, что предложил xophet, только у меня без копирования и вставок + дополнительные проверки. Работает она, конечно, быстрее, но в данном случае нужно выбирать, стоит ли оптимизировать. Если данный метод будет работать с большим текстом (тысячи символов), либо если будет очень часто вызываться, то тогда стоит задуматься об оптимизации, так как увеличение скорости может быть существенным. Иначе проще использовать регулярные выражения. Пример такой оптимизации: Code: private static Random _rand = new Random(); *** private static string Generate(string str) { int begPosition = -1; List<int> separatorsPos = new List<int>(); StringBuilder strBuilder = new StringBuilder(str); for (int i = 0; i < strBuilder.Length; ++i) { if (strBuilder[i] == '{') { begPosition = i; } else if (strBuilder[i] == '}' && begPosition != -1) { for (int j = begPosition + 1; j < i; ++j) { if (strBuilder[j] == '|') { separatorsPos.Add(j); } } int offset = strBuilder.Length; int randValueIndex = _rand.Next(0, separatorsPos.Count + 1); if (separatorsPos.Count == 0) { // Удаляем скобку после x: {x} = {x strBuilder.Remove(i, 1); // Удаляем скобку перед x: {x = x strBuilder.Remove(begPosition, 1); } else if (randValueIndex == 0) { // Удаляем всё, что идёт после x: {x|1|2|..n} = {x strBuilder.Remove(separatorsPos[0], i - separatorsPos[0] + 1); // Удаляем скобку перед x: {x = x strBuilder.Remove(begPosition, 1); } else if (randValueIndex == separatorsPos.Count) { // Удаляем скобку после x: {1|2|..n|x} = {1|2|..n|x strBuilder.Remove(i, 1); // Удаляем всё, что идёт перед x: {1|2|..n|x = x strBuilder.Remove(begPosition, separatorsPos[randValueIndex - 1] - begPosition + 1); } else { // Удаляем всё, что идёт после x: {..n|x|..n} = {..n|x strBuilder.Remove(separatorsPos[randValueIndex], i - separatorsPos[randValueIndex] + 1); // Удаляем всё, что идёт перед x: {..n|x = x strBuilder.Remove(begPosition, separatorsPos[randValueIndex - 1] - begPosition + 1); } begPosition = -1; separatorsPos.Clear(); offset -= strBuilder.Length; i -= offset; } } return strBuilder.ToString(); }
Я представляю, насколько сложно устроен и трудозатратен регэксп. Я говорю о том, что программист не должен сам реализовывать подобную сложность, если она уже реализована. Если что-то можно записать в 3-х строчках против 30, то лучше этой простотой и воспользоваться. Это не критично для всяких регеров и спамеров. Мы тут не софт для космических аппаратов пишем, а менее критичные к ресурсам вещи. Да, и напиши-ка свой код здесь. Пусть для наглядности он здесь полежит, посмеёмся над говнокодом.
Версия БЕЗ регулярок Code: function CopyRandomizeText(s:string;var open,close:Integer):string; begin Result:=''; if (Pos('{',s)=0)or(Pos('}',s)=0) then Exit; open:=Pos('{',s); close:=Pos('}',s); Result:=Copy(s,open+1,close-open-1); end; function GetRandomTextFromRandomized(s:string):string; var DelimitedText:TStringList; begin if Pos('|',s)=0 then begin Result:=s; Exit; end; DelimitedText:=TStringList.Create; try ExtractStrings(['|'],[' '],PChar(s),DelimitedText); Result:=DelimitedText[Random(DelimitedText.Count)]; finally DelimitedText.Free; end; end; function GetRandomTextFromRandomized(s:string):string; var DelimitedText:TStringList; begin if Pos('|',s)=0 then begin Result:=s; Exit; end; DelimitedText:=TStringList.Create; try ExtractStrings(['|'],[' '],PChar(s),DelimitedText); Result:=DelimitedText[Random(DelimitedText.Count)]; finally DelimitedText.Free; end; end; function ReplaceAllRandomizersInText(s:string):string; var tmp:string; open,close:Integer; begin Result:=s; repeat tmp:=CopyRandomizeText(Result,open,close); if tmp='' then Exit; Delete(Result,open,close-open+1); Insert(GetRandomTextFromRandomized(tmp),Result,open); until tmp=''; end; procedure TfrmMain.btn1Click(Sender: TObject); var i:Integer; t1, t2, tf: int64; begin QueryPerformanceFrequency(tf); QueryPerformanceCounter(t1); for i:=1 to 1000 do begin ReplaceAllRandomizersInText(mmo1.Text); Application.ProcessMessages; end; QueryPerformanceCounter(t2); mmo1.text:='time = ' + floattostr((t2-t1) / tf); end; Версия с регулярками: Code: function StrReplaceOne(const Str, Str1, Str2: string): string; //заменяет в строке Str подстроку Str1 На строку Str2 var P, L: Integer; begin Result := str; L := Length(Str1); P := Pos((Str1),(Result)); // ищем подстроку if P > 0 then begin Delete(Result, P, L); // удаляем ее Insert(Str2, Result, P); // вставляем новую end; end; function CopyRandomizeText(s:string):string; var reg:TRegExpr; begin reg:=TRegExpr.Create; try Result:=''; reg.Expression:='{(.*?)}'; if reg.Exec(s) then Result:=reg.Match[1]; finally reg.Free; end; end; function ReplaceAllRandomizersInText(s:string):string; var tmp:string; open,close:Integer; begin Result:=s; repeat tmp:=CopyRandomizeText(Result); if tmp='' then Exit; StrReplaceOne(Result,'{'+tmp+'}',GetRandomTextFromRandomized(tmp)) until tmp=''; end; procedure TfrmMain.btn1Click(Sender: TObject); var i:Integer; t1, t2, tf: int64; begin QueryPerformanceFrequency(tf); QueryPerformanceCounter(t1); // for i:=1 to 1000 do begin ReplaceAllRandomizersInText(mmo1.Text); Application.ProcessMessages; end; QueryPerformanceCounter(t2); mmo1.text:='time = ' + floattostr((t2-t1) / tf); end; Можете сравнить: нигде никаких задержек не ставил, все честно. Результаты теста на куске текста 270 КБ, по которому в 26-ти местах раскиданы соответствующие группу вида Code: {aasdas das asd asdas da|asdasdas asd|SAD|AS|DA|SD|AS|DAS|D|AS|D|ASD|AS|D|ASD|AS|D|AS|DA|SDASDAS|DAS|DA|SD|SA|DAS|DA|SD|AS|DAS|D|ASD|AS|DAS|D|AS|DAS|D} Версия БЕЗ РЕГУЛЯРОК (1000 итераций) = 33,37 секунды Версия С РЕГУЛЯРКАМИ (1 итерация) = уже больше 10ти минут и она все еще не выполнилась. при чем нагрузка на проц не падает ниже 50% P.S. Rafaello - вместо тысячи слов ))))))))))))) Не-а, не представляете. Какую такую сложность? с каких пор скопировать подстроку из строки стало "сложностью"? Как мы видим в обоих вариантах количество строк примерно одинаково Я не знаю что лично Вы тут пишете (почему-то мне кажеться, что ничего), но Вам видимо не доводилось писать тот же спамер (хотя как же могло доводиться писать, если Вы ничего не пишете, кроме 2х страниц срача), который работает в 300 потоков (открою Вам большой секрет: в моем опыте загрузка процессора не поднялась болешь 50% т.к. один поток не может грузить больше одного ядра процессора. Будь потоков два - комп бы "умер")
предоставлю. если отвечаете за свои слова, будьте любезны - предоставьте 50 WMZ за совет. не мне нужно - собакам и кошкам в приютах.
1. вы это сейчас к чему? 2. большое спасибо за вашу отзывчивость но перед вами предоставили 4 разных варианта реализации совершенно бескорыстно.
Эээээ.... Регулярки на Дельфях? Я когда-то видел это убожество в действии, да. Но я говорил про регулярки на .NET, которые работают там очень шустро. Но на код, что ты тут привёл, смотреть просто грустно. Что с регулярками, что без них. Такое ощущение, что на дворе 1998-й год наступил...
Все что нужно Regex.Replace (String, MatchEvaluator) быстро, понятно, красивооо(можно и рекурсию для вложенных иголок сделать). KISS.
без них оказалось быстрее красивее и короче но пришлось немного подумать) в принципе с ними тоже хорошо смотрелось)
предоставили Вам, и за-бесплатно? во всём топике нашёл лишь одну правильную мессагу. всё остальное - "Если бы у меня был рот, то это был бы полный огород" --- добавлено --- посмотрел, что пишут в топике. тянет на двойку. спам - не так пишется. как правильно написать - "совершенно бескорыстно", за 100 WMZ )) скупой платит дважды, и наступает на свои грабли.
предоставьте аналогичные данные в .Net, посмотрим как у Вас "шустро" работает. Я почему-то уверен, что на аналогичном куске текста Вы не дождетесь ее выполнения. Ну вообще-то ночь была на дворе, тупанул. не спорю Ну Вы в курсе, что иначе повисла бы форма и время выполнения только увеличилось, да? P.S. к стати в случае с регулярками форма все равно повисла Это сделано исключительно ради того, чтобы в версии с регулярками меньше пришлось менять, и для наглядности того факта, что я нигде ничего не перемудрил. Да Вы не понимаете всю серьезность происходящего. Дождаться выполнения регулярки на куске текста не представлялось возможным, вполне возможно, что не совсем красиво написано (про regex.replace не знал, спасибо) и там еще какие-то косяки. Но регулярка-то не выполнилась за 10 минут, а одна итерация с copy-delete-insert выполнялась 0.03 секунды По-крайней мере я подтвердил свою точку зрения фактом. Все остальные (на данный момент) остались голословными Ваш код в студию.
Если вы вот "это" называете красивей: то дальнейшая дискуссия в принципе бессмысленна. Зачем конкатенацию в string.Format заключать string.Format(result + message), string.Format(result + message.Remove(firstq)? И если такая забота о скорости то в условии while неплохо бы присвоить значения firstq. Вот вам приблизительный пример с Regex.Replace(String, MatchEvaluator) Ну куда уж мне осознать всю не серьезность ситуации, с моим то не серьезным умом. Насчет 10 минут ожидания на 270кб текста: файл ~1,1 мегабайта, 35 вхождений {aasdas das asd asdas da|asdasdas asd|SAD|AS|DA|SD|AS|DAS|D|AS|D|ASD|AS|D|ASD|AS|D|A S|DA|SDASDAS|DAS|DA|SD|SA|DAS|DA|SD|AS|DAS|D|ASD|A S|DAS|D|AS|DAS|D}.