Форум: "Основная";
Текущий архив: 2005.09.11;
Скачать: [xml.tar.bz2];
ВнизФункция, вырезающая строку между двумя разделителями Найти похожие ветки
← →
Piter © (2005-08-19 21:28) [0]Ищу функцию, в которую передается 3 параметра: исходная строка и два разделителя.
Результатом является строка, находящяяся между этими двумя разделителями в исходной строке.
Ну хотелось бы как можно быстрее :)
прототип:function CutString(Src, BeginSeparator, EndSeparatpr: string): string
Примеры работы:
CutString("abcdefg", "ab", "ef") = "cd"
CutString("bbvatzq", "a", "b") = ""
← →
Джо © (2005-08-19 21:30) [1]А что там сложного? Обычный Pos + Copy. Или, если на то пошло, for := 1 to Length...
← →
Piter © (2005-08-19 21:34) [2]Еще пример:
CutString("bbvatzq", "b", "a") = "bv"
← →
Piter © (2005-08-19 21:35) [3]Джо © (19.08.05 21:30) [1]
требуется быстрый вариант, наверняка есть уже готовые функции... не хочу изобретать медленный велосипед.
← →
Piter © (2005-08-19 21:41) [4]Явот где-то нашел в своих архивах функцию эту:
function CuteString(BeginSeparator:string; EndSeparator:string; s:string):string;
var i, i2:integer;
substr:string;
begin
result:="";
if BeginSeparator="" then
i:=1
else
i:= PosJOH_MMX_a(BeginSeparator, s);
if i<>0 then
begin
inc(i, Length(BeginSeparator));
substr:=copy(s,i,length(s)-i+1);
if EndSeparator="" then
i2:=length(substr)+1
else
i2:=PosJOH_MMX_a(EndSeparator,SubStr);
inc(i2,i-1);
if i2>i then
Result:=Copy(s,i,i2-i);
end;
end;
она рабочая... только мне ее сейчас даже анализировать влом :)
Возможно, есть достаточно стандартные решения?
← →
Leonid Troyanovsky © (2005-08-19 21:59) [5]
> Piter © (19.08.05 21:41) [4]
> она рабочая... только мне ее сейчас даже анализировать влом
> :)
Т.е., ты подозреваешь, что нас в уикенд делать оное не ломает?
Тем более, что мы даже не знаем кто такой PosJOH_MMX_a.
--
Regards, LVT.
← →
Piter © (2005-08-19 22:16) [6]Leonid Troyanovsky © (19.08.05 21:59) [5]
Т.е., ты подозреваешь, что нас в уикенд делать оное не ломает?
да я же говорю о том, что есть стандартное решение. Может у кого есть - поделится тогда
А функцию я делал сам - поэтому уверен, что можно куда лучше :)
Тем более, что мы даже не знаем кто такой PosJOH_MMX_a.
ну это аналог POS, только более быстрый, взял с какого-то сайта, где проводились соревнования по этому делу.
← →
GuAV © (2005-08-19 23:07) [7]Piter © (19.08.05 21:41) [4]
> substr:=copy(s,i,length(s)-i+1);
> i2:=PosJOH_MMX_a(EndSeparator,SubStr);
ИМХО это плохо тем, что создаётся лишняя строка. Причём дляEndSeparator = ""
она уже результат, фигли ты ещё делаешь, а дляEndSeparator <> ""
неоправданные затраты, лучше искать конец через PosEx. Попробуй переделать PosJOH_MMX_a в PosEx ;)
Кстати, в ММХ уже другой победитель :)
http://dennishomepage.gugs-cats.dk/PosChallenge.htm
← →
Piter © (2005-08-19 23:16) [8]GuAV © (19.08.05 23:07) [7]
переделать PosJOH_MMX_a в PosEx
ну вот, только я переделал и захотел запостить, а ты уже предложил :)
Итак, мой вариант теперь таков:function CuteString(BeginSeparator:string; EndSeparator:string; var s:string):string;
var i, i2:integer;
begin
Result := "";
if BeginSeparator = "" then
i := 1
else
i := PosEx_Sha_IA32_3_a(BeginSeparator, s);
if i > 0 then
begin
inc(i, Length(BeginSeparator) );
if EndSeparator = "" then
i2 := Length(s) + 1
else
i2 := PosEx_Sha_IA32_3_a( EndSeparator, s, i);
if i2 > i then
Result := Copy(s, i, i2 - i);
end;
end;
← →
Piter © (2005-08-19 23:16) [9]Piter © (19.08.05 23:16) [8]
PosEx_Sha_IA32_3_a
это самый быстрый пока аналог PosEx
← →
OldNaum © (2005-08-20 03:00) [10]GuAV © (19.08.05 23:07) [7]
Спасибо за сайтец. Очень интересная "кладовая" ) Никогда не забуду длиннющие топики, где Вы, Defunct (если не ошибаюсь) и многие другие "ускоряли" Pos.
← →
Piter © (2005-08-20 12:00) [11]А у кого по сабжу соображения будут? :)
← →
Anatoly Podgoretsky © (2005-08-20 12:50) [12]Есть соображение, что его можно написать.
← →
Piter © (2005-08-22 03:53) [13]Anatoly Podgoretsky © (20.08.05 12:50) [12]
кого написать?
← →
Defunct © (2005-08-22 03:57) [14]> кого написать?
Миша ты же не тормоз?
Его - т.е. сабж.
← →
Piter © (2005-08-22 13:24) [15]Функцию? Это понятно, что ее можно написать, а что дальше?
Можно ОС написать. И программу управления ядерными ракетами - тоже можно написать.
Не понимаю - как это относится к теме ветке?
← →
Piter © (2005-08-22 13:25) [16]Я же не спрашивал - можно ли написать такую функцию.
Я просил наиболее оптимальный вариант.
Хотя бы оптимальнее моего в [8]
← →
Anatoly Podgoretsky © (2005-08-22 13:39) [17]Piter © (22.08.05 13:24) [15]
Не к теме ветки, а в первую очередь к сообщению номер 11, если соображения не нужны то зачем же спрашиваешь, по крайней мере предупреждай, что вопрос риторический.
← →
Leonid Troyanovsky © (2005-08-22 14:10) [18]
> 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.
← →
afanasic (2005-08-22 14:26) [19]А что мы будем делать в таком варианте:
CutString("cbcabdaca","b","a") = ???
Какое значние правильное:
"c",
"cabd" или
"cabdac"?
← →
afanasic (2005-08-22 14:27) [20]Ибо алгоритмы будут существенно различаться...
← →
Piter © (2005-08-22 14:51) [21]Anatoly Podgoretsky © (22.08.05 13:39) [17]
если соображения не нужны то зачем же спрашиваешь
а-а-а... ясно. То есть, на вопрос "Как написать функцию..." ответ "Можно написать" и является соображением? :)
Ок, ок, я не понял :)))
afanasic (22.08.05 14:26) [19]
А что мы будем делать в таком варианте:
CutString("cbcabdaca","b","a") = ???
= "c"
← →
Anatoly Podgoretsky © (2005-08-22 15:04) [22]Piter © (22.08.05 14:51) [21]
В 11 был задан совсем другой вопрос, соображения по "сабжу", а не "как написать функцию". Правильно формулировать вопросы это твоя задача. Предъявлять по этому поводу предензии по крайней мере некрасиво.
← →
Alx2 © (2005-08-22 15:09) [23]>Piter © (19.08.05 21:28)
Как велика (в среднем) строчка-аргумент?
← →
afanasic (2005-08-22 15:09) [24]Тогда, учитывая и такую подставу:
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;
← →
Anatoly Podgoretsky © (2005-08-22 15:15) [25]afanasic (22.08.05 15:09) [24]
Надо избежать использования Delete это очень медленная операция.
← →
afanasic (2005-08-22 15:19) [26]Вместо Delete(...)
St := Copy(St,k1,Length(st)-k1+1);
← →
Anatoly Podgoretsky © (2005-08-22 15:23) [27]Алгоритм долже быть примерно таким
Найти начало и записать его в переменную K
Если K>0 (здесь постановка отсутствует) тогда или выход или установка К=1
Далее если М = 0 (здесь постановка отсутствует), или выход или установка М=конец строкитогда концом считать последнюю позицию или выход из фукнции, поскольку условие не выполнилось, оставим это автору.
Если K и M равно 0 (постановка отсутствует) то выход или копирование с установкой других значений.
Кроме этого ответить на вопросы от других участников, какой должен быть вариант и уточнив постановку написать за пару минут функцию.
← →
Anatoly Podgoretsky © (2005-08-22 15:28) [28]afanasic (22.08.05 15:19) [26]
Шило на мыло, не надо ни удалять ни копировать. Надо найти начало и конец и работать уже с этим. Операции изменения строки очень медленные. Это выделение памяти (возможно освобождение старой), копирование информации. А в конце концов окажется, что от исходной строки в пару сотен килобай нужно только один/два символа. Автор заостряет вопрос как сделать это оптимально, а не как вообще сделать.
← →
Piter © (2005-08-22 15:53) [29]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 миллионе строк - не хватило вирт. памяти :)
← →
Piter © (2005-08-22 15:56) [30]afanasic (22.08.05 15:09) [24]
Delete(St,1,k1-1);
даже тестировать не имеет смысла. Будет ОЧЕНЬ долго...
← →
Piter © (2005-08-22 16:03) [31]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]
написать за пару минут функцию.
напишите
← →
Игорь Шевченко © (2005-08-22 16:04) [32]А можно вопрос? Где и когда эта функция будет вызываться ?
А то получится, как у Конецкого, что смысла ускорять ее будет ровно столько же, сколько в определении длины шага у старого мерина, которого ведут на живодерню.
← →
Piter © (2005-08-22 16:07) [33]Piter © (22.08.05 15:53) [29]
Пробовал тестировать на 1 миллионе строк - не хватило вирт. памяти :)
при этом обе функции демонстрирует, в общем, хорошее время.
На 300 тысяч строках все происходит не более 10-ти секунд
← →
Piter © (2005-08-22 16:09) [34]Игорь Шевченко © (22.08.05 16:04) [32]
А можно вопрос? Где и когда эта функция будет вызываться ?
Текущее время уже абсолютно приемлимо.
Теперь просто интересно - можно ли быстрее :)
То есть, можно то точно, но вот интересно посмотреть на реализацию.
А вообще - такая функция уже использовалась в двух проектах, теперь просто хочется выбрать один раз и навсегда самую быструю :)
← →
Игорь Шевченко © (2005-08-22 16:29) [35]Piter © (22.08.05 16:09) [34]
Я к чему спрашиваю - в несильно критичных местах я бы предпочел ясность и удобочитаемость кода в ущерб быстродействию.
← →
Leonid Troyanovsky © (2005-08-22 16:36) [36]
> Piter © (22.08.05 15:53) [29]
> Leonid Troyanovsky © (22.08.05 14:10) [18]
>
> сравнил :(
> Твой вариант в 20 раз медленнее.
20 это серьезно :)
Правда, пока непонятно, за счет, собс-но, чего.
По-поводу самого тестирования есть замечание,
т.е., на самом деле, на месте оптимизатора я
удалил бы оба цикла, бо ничего полезного они делают.
С другой стороны, такие вещи следует делать
примерно так: делаем цикл n раз, 2*n раз, 3*n раз
и строим зависимость T - n. Обычно это прямая
(не из нуля). Сравниваем только скорость (угол наклона).
Замечу, что еще одним подводным камнем может быть
порядок, т.е. после работы одного блока может
произойти, скажем, сброс страниц в своп.
Т.е., надо давать поработать и одной и другой функции,
возможно, в случайном порядке.
--
Regards, LVT.
← →
Defunct © (2005-08-22 16:38) [37]Piter © (22.08.05 16:09) [34]
можно, но не на IA-32
← →
Leonid Troyanovsky © (2005-08-22 16:40) [38]
> Leonid Troyanovsky © (22.08.05 16:36) [36]
> примерно так: делаем цикл n раз, 2*n раз, 3*n раз
> и строим зависимость T - n. Обычно это прямая
Фу-ты. Зависимость T от раз (1, 2, 3, ..)
Sorry.
--
Regards, LVT.
← →
Piter © (2005-08-22 17:00) [39]Игорь Шевченко © (22.08.05 16:29) [35]
в несильно критичных местах я бы предпочел ясность и удобочитаемость кода в ущерб быстродействию
ну не знаю. Это ведь функция сама в себе, оттестированная, черный ящик. Какая разница что там внутри? Известен алгоритм работы - а что еще надо?
Leonid Troyanovsky © (22.08.05 16:36) [36]
т.е., на самом деле, на месте оптимизатора я
удалил бы оба цикла, бо ничего полезного они делают
понятное дело, но причем же здесь это :)
Оптимизатор не вдается в подробности - что там делает функция CuteString и нужен ли возвращаемый результат. Главное, что функции исполняются.
А насчет из корректности - вроде обе функции верные значения возвращают, поэтому это я не тестировал.
Leonid Troyanovsky © (22.08.05 16:36) [36]
С другой стороны, такие вещи следует делать
примерно так: делаем цикл n раз, 2*n раз, 3*n раз
и строим зависимость T - n
ломало :)
Замечу, что еще одним подводным камнем может быть
порядок, т.е. после работы одного блока может
произойти, скажем, сброс страниц в своп
нет, тут я пробовал несколько раз и в разном порядке - ничего не меняется.
← →
Anatoly Podgoretsky © (2005-08-22 20:47) [40]Piter © (22.08.05 16:03) [31]
Anatoly Podgoretsky © (22.08.05 15:23) [27]
Найти начало и записать его в переменную K
Если K>0 (здесь постановка отсутствует
Вероятно, имелось в виду K<1.
Да именно так.
напишите
Еще чего, нет такого желания просто так делать, будет конкретная задача, то естественно напишу, а просто так тратить время не могу, есть более насущные задачи. Тем более при отсутствии точной постановки задачи.
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2005.09.11;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.01 c