![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Функция, вырезающая строку между двумя разделителями
Piter © (2005-08-19 21:28:00)Ищу функцию, в которую передается 3 параметра: исходная строка и два разделителя.
Результатом является строка, находящяяся между этими двумя разделителями в исходной строке.
Ну хотелось бы как можно быстрее :)
прототип:
function CutString(Src, BeginSeparator, EndSeparatpr: string): string
Примеры работы:
CutString('abcdefg', 'ab', 'ef') = 'cd'
CutString('bbvatzq', 'a', 'b') = ''
Piter (2005-08-22 16:03:00) [21]Anatoly Podgoretsky © (22.08.05 15:23) [27]
Найти начало и записать его в переменную K
Если K>0 (здесь постановка отсутствует
Вероятно, имелось в виду K<1.
Если K < 1 - то результат пустая строка, кроме случая когда BeginSeparator = '', тогда K = 1
Далее если М = 0 (здесь постановка отсутствует
Если M = 0 - то результат функции - пустая строка, кроме случаев EndSeparator = '', тогда M равен последнему символу во входящей строке
Anatoly Podgoretsky © (22.08.05 15:23) [27]
написать за пару минут функцию.
напишите
Piter (2005-08-22 15:56:00) [22]afanasic (22.08.05 15:09) [24]
Delete(St,1,k1-1);
даже тестировать не имеет смысла. Будет ОЧЕНЬ долго...
Piter (2005-08-22 15:53:00) [23]Leonid Troyanovsky © (22.08.05 14:10) [18]
сравнил :(
Твой вариант в 20 раз медленнее.
Если не возражаешь против такого теста:
procedure TForm1.Button1Click(Sender: TObject);
const
cSizeString = 300000; // массив для тестирования будет состоять из 300 тысяч строк
var
arr, ArrBeginSeparator, ArrEndSeparator: array of string;
i, CountSymbol: integer;
Time1, Time2: cardinal;
function GenerateString(Size: integer): string;
var
i: integer;
begin
SetLength(Result, Size);
Randomize;
for i := 1 to Length(Result) do
Result[i] := Chr (Random( ord('z') - ord('a') ) + ord('a') ); // символы генерятся от a до z
end;
begin
SetLength(arr, cSizeString);
SetLength(ArrBeginSeparator, cSizeString);
SetLength(ArrEndSeparator, cSizeString);
Randomize ;
for i := 0 to High(arr) do
begin
CountSymbol := Random(1000) + 5; // длина строк от 5 до 1000 символов
arr[i] := GenerateString(CountSymbol);
CountSymbol := Random(30) + 3; // длина разделителей от 3 до 30 символов
ArrBeginSeparator[i] := GenerateString(CountSymbol);
CountSymbol := Random(30) + 3; // длина разделителей от 3 до 30 символов
ArrEndSeparator[i] := GenerateString(CountSymbol);
end;
Time1 := GetTickCount;
for i := 0 to High(arr) do
CuteStringMy(arr[i], ArrBeginSeparator[i], ArrEndSeparator[i]);
Time1 := GetTickCount - TIme1;
Time2 := GetTickCount;
for i := 0 to High(arr) do
CuteStringLVT(arr[i], ArrBeginSeparator[i], ArrEndSeparator[i]);
Time2 := GetTickCount - TIme2;
showmessage(IntToStr(Time1) + #13#10 + IntToStr(Time2));
end;
Готовый проект - http://piter.pechora.org/temp/test_cute_string_Piter_vs_LVT.zip
Пробовал тестировать на 1 миллионе строк - не хватило вирт. памяти :)
Anatoly Podgoretsky (2005-08-22 15:28:00) [24]afanasic (22.08.05 15:19) [26]
Шило на мыло, не надо ни удалять ни копировать. Надо найти начало и конец и работать уже с этим. Операции изменения строки очень медленные. Это выделение памяти (возможно освобождение старой), копирование информации. А в конце концов окажется, что от исходной строки в пару сотен килобай нужно только один/два символа. Автор заостряет вопрос как сделать это оптимально, а не как вообще сделать.
Anatoly Podgoretsky (2005-08-22 15:23:00) [25]Алгоритм долже быть примерно таким
Найти начало и записать его в переменную K
Если K>0 (здесь постановка отсутствует) тогда или выход или установка К=1
Далее если М = 0 (здесь постановка отсутствует), или выход или установка М=конец строкитогда концом считать последнюю позицию или выход из фукнции, поскольку условие не выполнилось, оставим это автору.
Если K и M равно 0 (постановка отсутствует) то выход или копирование с установкой других значений.
Кроме этого ответить на вопросы от других участников, какой должен быть вариант и уточнив постановку написать за пару минут функцию.
afanasic (2005-08-22 15:19:00) [26]Вместо Delete(...)
St := Copy(St,k1,Length(st)-k1+1);
Anatoly Podgoretsky (2005-08-22 15:15:00) [27]afanasic (22.08.05 15:09) [24]
Надо избежать использования Delete это очень медленная операция.
afanasic (2005-08-22 15:09:00) [28]Тогда, учитывая и такую подставу:
CutString('abcd','abc','bcd'), очень просто и достаточно быстро, причем вместо Pos можно использовать любую функцию, которая быстрее:
function CutString(St, BegSt, EndSt: String): String;
var
k1,k2,n: Integer;
begin
Result := '';
// поищем первую строку
k1 := Pos(BegSt,St);
// если есть, то будем искать вторую после первой
if k1 > 0 then
begin
Delete(St,1,k1-1);
k2 := Pos(EndSt,St);
if k2 > 0 then
begin
n := Length(BegSt);
Result := Copy(st,n+1,k2-n-1);
end;
end;
end;
Alx2 (2005-08-22 15:09:00) [29]>Piter © (19.08.05 21:28)
Как велика (в среднем) строчка-аргумент?
Anatoly Podgoretsky (2005-08-22 15:04:00) [30]Piter © (22.08.05 14:51) [21]
В 11 был задан совсем другой вопрос, соображения по "сабжу", а не "как написать функцию". Правильно формулировать вопросы это твоя задача. Предъявлять по этому поводу предензии по крайней мере некрасиво.
Piter (2005-08-22 14:51:00) [31]Anatoly Podgoretsky © (22.08.05 13:39) [17]
если соображения не нужны то зачем же спрашиваешь
а-а-а... ясно. То есть, на вопрос "Как написать функцию..." ответ "Можно написать" и является соображением? :)
Ок, ок, я не понял :)))
afanasic (22.08.05 14:26) [19]
А что мы будем делать в таком варианте:
CutString('cbcabdaca','b','a') = ???
= 'c'
afanasic (2005-08-22 14:27:00) [32]Ибо алгоритмы будут существенно различаться...
afanasic (2005-08-22 14:26:00) [33]А что мы будем делать в таком варианте:
CutString('cbcabdaca','b','a') = ???
Какое значние правильное:
'c',
'cabd' или
'cabdac'?
Leonid Troyanovsky (2005-08-22 14:10:00) [34]
> Piter © (22.08.05 13:25) [16]
> Я же не спрашивал - можно ли написать такую функцию.
> Я просил наиболее оптимальный вариант.
>
> Хотя бы оптимальнее моего в [8]
Вот тебе еще вариант (сделан на коленке).
Теперь можешь и сравнивать.
function CutString(const Src, BeginSeparator, EndSeparator: string): string;
var
p, p1, p2, pe : PChar;
begin
p := PChar(src);
p1 := nil;
p2 := nil;
pe := p + Length(Src);
while (p <= pe) and not Assigned(p2) do
begin
if StrLComp(p, PChar(BeginSeparator), Length(BeginSeparator)) = 0 then
begin
p1 := p + Length(BeginSeparator);
p := p1;
while p <= pe do
begin
if StrLComp(p, PChar(EndSeparator), Length(EndSeparator)) = 0 then
begin
p2 := p;
Break;
end
else
inc(p);
end;
end
else
inc(p);
end;
if Assigned(p2) then
SetString(Result, p1, p2-p1);
end;
--
Regards, LVT.
Anatoly Podgoretsky (2005-08-22 13:39:00) [35]Piter © (22.08.05 13:24) [15]
Не к теме ветки, а в первую очередь к сообщению номер 11, если соображения не нужны то зачем же спрашиваешь, по крайней мере предупреждай, что вопрос риторический.
Piter (2005-08-22 13:25:00) [36]Я же не спрашивал - можно ли написать такую функцию.
Я просил наиболее оптимальный вариант.
Хотя бы оптимальнее моего в [8]
Piter (2005-08-22 13:24:00) [37]Функцию? Это понятно, что ее можно написать, а что дальше?
Можно ОС написать. И программу управления ядерными ракетами - тоже можно написать.
Не понимаю - как это относится к теме ветке?
Defunct (2005-08-22 03:57:00) [38]> кого написать?
Миша ты же не тормоз?
Его - т.е. сабж.
Piter (2005-08-22 03:53:00) [39]Anatoly Podgoretsky © (20.08.05 12:50) [12]
кого написать?
Anatoly Podgoretsky (2005-08-20 12:50:00) [40]Есть соображение, что его можно написать.