Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.09.10;
Скачать: CL | DM;

Вниз

Разбиение строки в масив   Найти похожие ветки 

 
Селезин ©   (2006-08-21 11:36) [0]

Тема, наверное, старая и известная. Спрашиваю не ради решения, а ради лучшего решения.
Имеется строка с разделителями внутри (типа "aa1|bb2|cc3"). Нужно разить ее и загнать в массив ["aa1","bb2","cc3"] в D7. Вариантов решения, конечно, море (насколько я знаю, стандартной функции нет). А как бы это сделать с наименьшими затратами?


 
unknown ©   (2006-08-21 11:45) [1]


> Селезин ©   (21.08.06 11:36)

Tstrings - вместо самопального массива.
Далее
var str:TStrings;
begin
 Str:=TStringList.Create;
 Str.DelimiterL="|";
 Str.DelimitedText:="aa1|bb2|cc3";
end;


 
default ©   (2006-08-21 11:46) [2]

например,
просматриваешь входную строку посимвольно для подсчёта разделителей
потом в соответствии с числом разделителей выделяешь память для нужного числа элементов - строк в массиве
затем опять просматриваешь входную строку посимвольно
как только встретился разделитель выделяешь нужный размер памяти для строки соответствующего элемента массива и копируешь туда(не обязательно побайтово) строку соответствующую разделителю и тд


 
unknown ©   (2006-08-21 11:46) [3]

Очепятка, Str.Delimiter:="|";


 
Селезин ©   (2006-08-21 12:15) [4]

------------
Tstrings - вместо самопального массива.
Далее
var str:TStrings;
begin
 Str:=TStringList.Create;
 Str.DelimiterL="|";
 Str.DelimitedText:="aa1|bb2|cc3";
end;

-------------
А если текст такой (а он почти везде подобный).
"Мои имя фамилия отчество#мой адрес#мои интересы#мой e-mail"?
Насколько я понял из inet"а, DelimitedText разбивает и по пробелам и по чему-то еще там.


 
default ©   (2006-08-21 12:21) [5]

Селезин ©   (21.08.06 12:15) [4]
ты что с другой планеты явился?
Str.DelimiterL="#";


 
Селезин ©   (2006-08-21 12:43) [6]

---from http://www.delphikingdom.com/asp/answer.asp?IDAnswer=29705 ---
Зря смеетесь. Сергей Осколков абсолютно прав. Тупое использование DelimitedText делит не только по знаку деления скажем ";" но и по пробелам. поэтому если строка A;B;C;D может содержать пробелы, то DelimitedText разбивает и по пробелам.
------------------
Еще цитаты надо?


 
Плохиш ©   (2006-08-21 12:52) [7]


> Селезин ©   (21.08.06 12:43) [6]
> Еще цитаты надо?

Зачем нам тупые цитаты, мы и в генофонд не гнушаемся заглядывать. Время на создание функции с требуемым Вам результатом 10 минут.


 
Селезин ©   (2006-08-21 13:05) [8]

Неа, две минуты, с учетом моей орфографической правильности печати текста. Но меня интересует как-то время выполнения и затребываемая память, а не время создания (о чем специально указал в начале темы).


 
begin...end ©   (2006-08-21 13:07) [9]

> Селезин ©   (21.08.06 12:15) [4]

> А если текст такой (а он почти везде подобный).
> "Мои имя фамилия отчество#мой адрес#мои интересы#мой e-mail"?

Classes.ExtractStrings


 
default ©   (2006-08-21 14:09) [10]

только пусть автор сабжа имеет ввиду, что Classes.ExtractStrings тоже не без греха
" while (InQuote and not (Tail^ in ["""", """, #0])) or
         not (Tail^ in Separators + [ #0, #13, #10, """", """]) do Inc(Tail);"
даже по двойной кавычке обрезает...

чтобы разбиение проводилось только по нужным разделителям пиши свою


 
Селезин ©   (2006-08-21 14:56) [11]

Да я уже написал, даже в трех вариантах :)
Просто задумался - может есть более простой путь?


 
Пусик ©   (2006-08-21 14:59) [12]


> Селезин ©   (21.08.06 14:56) [11]


Мне кажется, что простой проход по строке с одновременным помещением подстрок в динамический массив будет приемлимым решением с любой точки зрения.


 
easy ©   (2006-08-21 15:06) [13]

type TStrarray = array of string;

function explode(instr: string; const delmtr:char; var outarr: TStrarray): boolean;  //[x]
var
 len, j : integer;
 tmp:string;
begin
 j := pos(delmtr, instr);
 len := 0;
 result := false;
 if j <> 0 then begin
   while j <> 0 do begin
     tmp := copy(instr, 1, j - 1);
     SetLength(outarr, len+1);
     outarr[len] := tmp;
     inc(len);
     delete(instr, 1, j);
     j := pos(delmtr, instr);
   end;
   tmp := instr;
   SetLength(outarr, len+1);
   outarr[len] := tmp;
   result := true;
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 A:TStrarray;
begin
 if explode("Мои имя фамилия отчество#мой адрес#мои интересы#мой e-mail","#",A) then
   Showmessage(A[High(A)]);
end;


 
Селезин ©   (2006-08-21 15:06) [14]

Хм, не знаю, как с точки зрения времени и памяти, учитывая, что придется разбирать единовременно порядка 500-5000 строк из 20-50 разделителей каждая.

default, а ссылка на описание "погрешностей" Classes.ExtractStrings есть? Дабы на грабли не наступить потом случайно.


 
XTD ©   (2006-08-21 15:12) [15]

var t:TStringList;

begin
 t:=TStringList.create; //создаём класс
 t.text:=stringReplace("Ваша строка для разделения"," ",#13#10,[rfReplaceAll]);//мы заменяем все пробелы на символы конца строки
//теперь можно убедится что у вас строка разбина на элементы:
 showmessage(t[0]);
 showmessage(t[1]);
 showmessage(t[2]);
 showmessage(t[3]);
...
//после работы надо уничтожить класс
t.free;


 
Пусик ©   (2006-08-21 15:26) [16]

Разбивка в один цикл:

function ExtractStrings(const Src: String; StrArray: TStrArray; Delim: Char): Integer;
var
 pz: Integer;
 i: Integer;
begin
 Result := -1;
 if Length(Src)=0 then
 begin
   Result := 0;
   Exit;
 end;
 pz := 1;
 i := 1;
 if Length(StrArray)=0 then SetLength(StrArray,128);
 while i<Length(Src) do
 begin
   if Src[i]=Delim then
   begin
     Inc(Result);
     if Result=Length(StrArray) then SetLength(StrArray,Length(StrArray)+128);
     StrArray[Result] := Copy(Src,pz,i-pz);
     Inc(i);
     pz := i;
   end
   else Inc(i);
 end;
 if pz<>Length(Src) then
 begin
     Inc(Result);
     if Result=Length(StrArray) then SetLength(StrArray,Length(StrArray)+1);
     StrArray[Result] := Copy(Src,pz,Length(StrArray)-pz+1);
 end;
 Inc(Result);
 SetLength(StrArray,Result);
end;


 
default ©   (2006-08-21 15:27) [17]

Селезин ©   (21.08.06 15:06) [14]
см [7]
генофонд - это исходники
в них можно посмотреть код этой функции
это куда лучше чем подбирать комментарии всяких с разных сайтов о данной проблематике...первоисточник всегда рулит


 
Селезин ©   (2006-08-21 15:57) [18]

default
В смысле вытащить из исходника и преобразовать под себя?
Ну и так тоже иногда делаем. Вопрос в том, что надо сперва допереть что вытаскивать. И стоит ли овчинка выделки.

Типа ЛЮБОЙ алгоритм использует простой перебор? В том числе и дельфийские функции?
Тогда вопрос, скажем pos работает быстрее, чем самоличный перебор по поиску разделителя или медленнее?
то бишь быстрее будет работать

j := pos("#", strResurs);

или

j:=1;
while (copy(strResurs, j, 1)<>"#") do inc(j);
end;


 
Zeqfreed ©   (2006-08-21 16:05) [19]

> [18] Селезин ©   (21.08.06 15:57)


> copy(strResurs, j, 1)<>"#"

Зачем такой ужас?


 
Селезин ©   (2006-08-21 16:25) [20]

Ну хорошо,

j:=1;
while (strResurs[j]<>"#") do inc(j);

Но смысл вопроса тот же.


 
Пусик ©   (2006-08-21 16:27) [21]


> Тогда вопрос, скажем pos работает быстрее, чем самоличный
> перебор по поиску разделителя или медленнее?


А тебе Pos подойдет для поиска сразу всех разделителей?;)


 
Плохиш ©   (2006-08-21 16:28) [22]


> Селезин ©   (21.08.06 16:25) [20]

Рекомендую всё-таки посмотреть реализацию SetDelimitedText у TStrings.


 
Gydvin ©   (2006-08-21 18:22) [23]

Ну, а чем плох такой вариант

procedure TForm1.Button1Click(Sender: TObject);
var
 arr: array of string;
 s: string;
 x, i: integer;
begin

 s := "Мама#мыла#очень#большой#кусок#подоконика#от#уличной#рамы#";

 i := 0;

 for x := 1 to length(s) do if s[x] = "#" then inc(i);
 setlength(arr, i);

 i := 0;

 for x := 1 to length(s) do begin
   if s[x] = "#" then inc(i)
   else arr[i] := arr[i] + s[x];
 end;

 showmessage(arr[0]);
 showmessage(arr[1]);
 showmessage(arr[2]);
 showmessage(arr[3]);
 showmessage(arr[4]);
 showmessage(arr[5]);
 showmessage(arr[6]);
 showmessage(arr[7]);
 showmessage(arr[8]);

end;


 
default ©   (2006-08-21 18:40) [24]

Gydvin ©   (21.08.06 18:22) [23]
"Ну, а чем плох такой вариант"
честно говоря, лучше бы ты его не приводил...
"arr[i] := arr[i] + s[x];"
тут будут возникать перераспределения памяти


 
Gydvin ©   (2006-08-21 18:41) [25]

последний # из строки убрать


 
Gydvin ©   (2006-08-21 18:50) [26]


> тут будут возникать перераспределения памяти

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

ЗЫ щас пересмотрел ветку с начала в 2 ты предлогал собсна тоже самое. Не (использовать же copy для вставки в массив)


 
Селезин ©   (2006-08-22 00:39) [27]

А чем плох Copy?
-----
Вообще-то вопрос был - какой алгоритм будет работать быстрее всего и с меньшими затратами памяти? До сих пор нет ни одного ответа на ЭТОТ вопрос.


 
Ketmar ©   (2006-08-22 00:48) [28]

> [27] Селезин ©   (22.08.06 00:39)
ассемблерный. оптимизированный руками под каждый процессор.


 
Селезин ©   (2006-08-22 02:29) [29]

> [28] Ketmar ©   (22.08.06 00:48)
:) Спасибо..


 
guav ©   (2006-08-22 02:39) [30]

Если можно обойтись элементами выходного массива типа PChar, то сохранить где-либо строку, в цикле заменять разделители на #0 и запоминать начала подстрок.


 
Пусик ©   (2006-08-22 11:31) [31]


> Селезин ©   (22.08.06 00:39) [27]
> А чем плох Copy?-----Вообще-то вопрос был - какой алгоритм
> будет работать быстрее всего и с меньшими затратами памяти?
>  До сих пор нет ни одного ответа на ЭТОТ вопрос.


У тебя есть несколько вариантов. Тестируй, проверяй.

При желании, можешь реализовать наиболее эффективные алгоритмы:
http://alglib.sources.ru/
http://algolist.manual.ru/



Страницы: 1 вся ветка

Текущий архив: 2006.09.10;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.035 c
1-1154280131
Lordalexander
2006-07-30 21:22
2006.09.10
Прозрачный Label


15-1155811350
Layner
2006-08-17 14:42
2006.09.10
Сок, который в коробках продается по 0,2/0,5/1...


3-1151221954
Rama
2006-06-25 11:52
2006.09.10
Трехзвенная архитектура


8-1140628607
Sour Smile
2006-02-22 20:16
2006.09.10
Как правильно нарисовать дым?


15-1155928156
ronyn
2006-08-18 23:09
2006.09.10
Как прописать программно приложение в автозагрузку?