Форум: "Начинающим";
Текущий архив: 2006.09.10;
Скачать: [xml.tar.bz2];
ВнизРазбиение строки в масив Найти похожие ветки
← →
Селезин © (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;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.046 c