Нужна помощь Explode;

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Нужна помощь Explode;

Сообщение vitaly_l » 14.03.2014 00:43:03

Всем привет,
сделал функцию explode, с помощью UTF8Pos();
Всё в ней хорошо... вот только фурычит такая функция медленно...
Пока UTF8Pos найдёт... пока Copy сделает...
В общем 40 000 записей при Explode на строки, а строки на 7 полей - заняло аж за 10-15 минут...
А в итоге надо делать Explode миллион записей... соответственно ждать исполнения долго...

Вроде при переводе из utf в ansi стало побыстрее (по крайней мере разбиение на строки заняло секунды)...
Дальше пока не пробовал и решил спросить совет. Как правильно сделать Explode (как в PHP)?
В PHP Explode: эти же 40 000 строк - разбиваются быстро. Значит можно как-то и здесь сделать... Да?

вот это уже читал http://www.freepascal.ru/forum/viewtopic.php?f=1&t=1591&p=9440&hilit=Explode#p9440

:| Дайте совет, прлиииииз :cry:


.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Нужна помощь Explode;

Сообщение alexs » 14.03.2014 01:53:20

А код какой?
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4064
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Нужна помощь Explode;

Сообщение vitaly_l » 14.03.2014 09:47:16

alexs писал(а):А код какой?

Ууууу.... Если Вы, alexs, пишите, что совет (в изложенной ситуации) дать сложно...
То тогда, похоже мои дела плохи (т.к. сделал всё правильно)...
В любом случае спасибо, т.к. это тоже полезная информация.


.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Нужна помощь Explode;

Сообщение alexs » 14.03.2014 09:55:45

Просто там несколько путей решения. Самый быстрый - не пользоваться вообще Pos (UTF8Pos) и строковым представлением. Работать на уровне плоского массива байт и побайтно аккуратно проводить сравнение. Побайтно же и копировать с помощью Move.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4064
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Нужна помощь Explode;

Сообщение zub » 14.03.2014 11:28:19

>>заняло аж за
Дайте угадаю, код изобилует конструкциями вида
s:=s+какаятострока[i]
?
alexs
+1
Работать можно и на уровне строк, но надо позаботится чтоб небыло лишних выделений\перераспределений памяти
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Нужна помощь Explode;

Сообщение vitaly_l » 14.03.2014 11:38:36

zub писал(а):Дайте угадаю, код изобилует конструкциями вида
s:=s+какаятострока[i]

нет не угадали...
там разделителем были двойные символы... это тоже замедляет... сейчас их заменил на единичные, тестирую..
код выглядит так:
arrStr := UTF8Explode('`',sReturnText);
arrData := UTF8Explode('|' , arrStr[j]');

Добавлено спустя 5 минут 56 секунд:
zub писал(а):надо позаботится чтоб небыло лишних выделенийперераспределений памяти

Уверены в этом??? Там 1 000 000... вообще alexs правильно сказал про move... я им давно не пользовался, т.к. на другом языке делал.
А например при обработке 3d массивов, используют только move... соответственно alexs правильно сказал... Я так думаю...
Разве нет?

.

Добавлено спустя 5 минут 3 секунды:
Я ещё нашёл вот такую функцию... ExtractWord (это стандартный explode lazarusa)
Она быстро работает??? (думаю, что медленно, т.к. она вначале для каждой ищет её начало, а не делит все подряд...)

Добавлено спустя 1 минуту 34 секунды:
Вот её код... там как раз Move используют...

Код: Выделить всё
function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
var
  i,j,l: Integer;
begin
  j:=0;
  i:=WordPosition(N, S, WordDelims);
  Pos:=i;
  if (i<>0) then
    begin
    j:=i;
    l:=Length(S);
    while (j<=L) and not (S[j] in WordDelims) do
      inc(j);
    end;
  SetLength(Result,j-i);
  If ((j-i)>0) then
    Move(S[i],Result[1],j-i);
end; 


Добавлено спустя 23 минуты 21 секунду:
Но вот что странно...
PHP даже с двойными символами разделения - разбивает быстро...
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Нужна помощь Explode;

Сообщение zub » 14.03.2014 12:45:18

>>Уверены в этом??? Там 1 000 000...
Ты не понял, я говорю о таких вещах:
Код: Выделить всё
  SetLength(Result,j-i);
  If ((j-i)>0) then
    Move(S[i],Result[1],j-i);

т.е. выделил память под строку за один раз, а потом копируй, хоть посимвольно, хоть move. Не важно как ты представляешь исходный и целевой текст - массивом или строкой, правильно написаный код даст почти одинаковые результаты (с оговоркой на некоторые дополнительные проверки которые компилятор делает для строк, но это никак не 10-15мин рантайма)

>>Вот её код... там как раз Move используют...
>>PHP даже с двойными символами разделения - разбивает быстро...
доработай код чтоб небыло поиска каждый раз с самого начала, для "неодинарных разделителей". что мешает то? а потом уже будем рассуждать откуда тормоза))

кстати,
>>сделал функцию explode, с помощью UTF8Pos();
в данном случае без разницы что ты используешь, анси или утф8. утф8 проглатывается парсерами расчитанными на анси на ура
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Нужна помощь Explode;

Сообщение vitaly_l » 14.03.2014 13:00:59

zub писал(а):доработай код чтоб небыло поиска каждый раз

Да это понятно.
zub писал(а):т.е. выделил память под строку за один раз

Без принудительного указания на выделение памяти - оно медленнее работает? (что-то мне подсказывает, что уже спорили на эту тему)

Кстати, как заменить s:=s+какаятострока[i]?
Строки можно как-то иначе сцепить в одну строку?



.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Нужна помощь Explode;

Сообщение xdsl » 14.03.2014 13:47:38

vitaly_l писал(а):Кстати, как заменить s:=s+какаятострока[i]?
Строки можно как-то иначе сцепить в одну строку?

Если s - shortstring, то никаких проблем, но длина - до 256 байт: s[ord(s[0])+1]:= какаятострока[i]; inc(s[0]);
Если s - ansistring или widestring, то придется перераспределять оперативную память. С учетом экзотичности структуры таких строк, выйдет как-бы не дольше, чем Ваш вариант.
Можно попробовать вариант с PChar будет, имхо, эффективнее всего.
xdsl
постоялец
 
Сообщения: 131
Зарегистрирован: 15.01.2009 13:49:03

Re: Нужна помощь Explode;

Сообщение SSerge » 14.03.2014 14:01:43

xdsl писал(а):Можно попробовать вариант с PChar будет, имхо, эффективнее всего.


Не всегда. При операциях с PChar иногда тоже могут генерироваться промежуточные строковые переменные. Строго зависит от того, что написано, конечно же. Иные конструкции вроде бы и не должны генерировать лишнее распределение памяти, ан нет... В любом случае, пока не оттранслируешь в ассемблер, дополнительных вызовов не увидеть.

Голосую за PChar, однако.
В любых случаях, где появляются паскалевские строки, быстродействие будет провальным, до сливания в разы явам и даже php с perlом, что и наблюдается

Добавлено спустя 3 минуты 8 секунд:
vitaly_l писал(а):код выглядит так:
arrStr := UTF8Explode('`',sReturnText);
arrData := UTF8Explode('|' , arrStr[j]');



От этого то кода какой прок? Спрашивали о реализации UTF8Explode
SSerge
энтузиаст
 
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Re: Нужна помощь Explode;

Сообщение vitaly_l » 14.03.2014 21:53:19

Тяжело быть художником...
xdsl писал(а):Если s - shortstring, то никаких проблем, но длина - до 256 байт: s[ord(s[0])+1]:= какаятострока[i]; inc(s[0]);

не.. там в итоге получается очень длинная строка...

А вот так правильно их склеивать? (я про стринги)
:arrow: sMyStr := strcat( ' правильно и быстро ',' склеить строки ' );???
При условии что, нужно склеить while i < 1000000 do sMyStr := strcat( ' правильно и быстро ',' склеить строки ' );

Добавлено спустя 12 минут 31 секунду:
Нет так делать нельзя, т.к. падает... из-за длинной строки...


.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Нужна помощь Explode;

Сообщение скалогрыз » 14.03.2014 22:59:22

vitaly_l писал(а):А вот так правильно их склеивать? (я про стринги)

ответ прост - склеивать их нельзя вообще.
правильно выделить память под строку один раз (с избытком, т.к. реально требуемый размер строки заранее неизвестен), а потом просто переносить куски памяти (либо из "стога" либо из "иголки", выражаясь терминами php).
в итоге, уменьшить размер строки до необхимого (причём не факт, что уменьшение строки физически перераспределит память) - почти бесплатная операция.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Нужна помощь Explode;

Сообщение Mirage » 15.03.2014 14:58:31

Зачем вообще что-то склеивать? Explode же разделяет строки?
Т.е. фактически это split(), просто неудачное название из пхпшечки зачем-то кто-то притащил.
Mirage
энтузиаст
 
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Нужна помощь Explode;

Сообщение vitaly_l » 15.03.2014 15:08:28

Вначале решали вопрос разделения...
И добрый zub решил угадать на что тратится время...
И поднялся закономерный вопрос, не только разделения, но и склеивания.
С разделением разобрались, т.к. вместо 15 минут моей функции (при помощи UTF8Pos и ошибки),
взятый из unit-ов лазаруса код, после переделки(под другие задачи) - стал разбивать массив 300 000 меньше секунды...

А вот со склеиванием строк... добрые программисты утаили секреты склеивания от художников...
И поэтому вопрос "склеивания громадных строк" из множества маленьких - всё ещё актуален.



.
Последний раз редактировалось vitaly_l 15.03.2014 15:35:09, всего редактировалось 1 раз.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Нужна помощь Explode;

Сообщение alexs » 15.03.2014 15:34:06

Элементарно
Выдели сразу память под итоговую строку
А потом через Move вноси в неё значения.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4064
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 238

Рейтинг@Mail.ru