Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.047 c
3-1152192063
mefisto
2006-07-06 17:21
2006.09.10
"Наглядный" SQL Запрос : )


2-1155884743
her
2006-08-18 11:05
2006.09.10
TBytes и TIdSocketHandle


5-1139301255
Priest
2006-02-07 11:34
2006.09.10
Делегирование реализации интерфейсов


6-1145631768
M@D
2006-04-21 19:02
2006.09.10
Error (INDY)


15-1155800785
Сергей М.
2006-08-17 11:46
2006.09.10
Непонятка при работе в связке Access2003 + MS VisualFoxPro ODBC





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский