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

Вниз

Поиск в TStringList по первым символам его строк.   Найти похожие ветки 

 
Кириешки ©   (2004-11-19 11:28) [0]

Есть TStringList содержащий 97 тыс. строк загружаемых из файла.
Мне надо чтобы можно было производить поиск в нем по ПЕРВЫМ символам его строк. Ну, чтобы было примерно так :
Допустим есть TStringList заполненый n-ным кол-вом строк, листбокс и едит. В едите пишется например "аб" и в листбокс поподают все строки из TStringList начинающиеся на "аб". Подскажите пожалуйста как это реализовать, и если можно с примерчиком.


 
ЮЮ ©   (2004-11-19 11:36) [1]

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


 
Кириешки ©   (2004-11-19 11:41) [2]

ЮЮ

А как искать - то я не понял?


 
sniknik ©   (2004-11-19 11:43) [3]

len:= Length(Edit.Text);
for i:= 0 to StringList.Count-1 do
 if copy(StringList.Strings[i], 1, len)="аб" then
  листбокс.Add(StringList.Strings[i]);

но вообщето с 97 тыс строк уже можно думать о базах данных ;о)). или хотябы использовать базовые компоненты с их фильтрами, индексами, сортировкой, ...


 
begin...end ©   (2004-11-19 11:49) [4]


> [2] Кириешки ©   (19.11.04 11:41)


> А как искать - то я не понял?

Та же написано - методом половинного деления.


 
ЮЮ ©   (2004-11-19 11:52) [5]

ну, например, так:

function FindFirst(List:TstringList; const Mask: String): integer;
var
 cr, l, len, r, t: integer;
begin
 if Mask = "" then begin
   Result := -1;
   Exit;
 end;
 len := length(Mask);
 l := 0;
 r := List.Count - 1;
 t := (l + r) div 2;
 while l <= r do begin
   cr := AnsiCompareText(Copy(List[t], 1, len), Mask);
   if cr = 0 then begin
     result := t;
     exit;
   end else if cr < 0 then
     l := t + 1
   else
     r := t - 1;
   t := (l + r) div 2;
 end;
 result := -1;
end;


 
***SPIDER***   (2004-11-19 11:55) [6]

Примерно так:
...
StringList1.LoadFromFile(...);
...
procedure TForm1.Edit1Change(...);
var i,n:integer;
begin
 ListBox1.Clear;
 if StringList1.Count>0 then
 for i:=0 to StringList1.Count-1 do
 begin
   if Copy(StringList1.Strings[i],1,Length(Edit1.Text))=Edit1.Text then
   ListBox1.Items.Add(StringList1.Strings[i]);
 end;
end;
...

Конечно методом половинного деления будет эффективнее, но лень писать.


 
Кириешки ©   (2004-11-19 12:07) [7]

Спасибо всем!

А что такое метод половинного деления? :((


 
ЮЮ ©   (2004-11-19 12:13) [8]

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


 
begin...end ©   (2004-11-19 12:22) [9]


> [7] Кириешки ©   (19.11.04 12:07)

> А что такое метод половинного деления?


Попробую объяснить. Только прошу всех не делать выводов о моей озабоченности. Я просто посмотрел на адрес e-mail товарища Кириешки.

Вот представь. Находишься ты в коридоре, в котором есть ряд из 11 дверей. За дверьми, в комнатах, сидят женщины - по одной в каждой комнате. Известно, что чем больше номер двери, тем больше возраст женщины, находящейся в соответствующей комнате. Тебе, например, нравятся только 20-летние.

Заходишь ты в среднюю (6-ю) дверь. А там сидит 10-летняя девочка. Понятно, что за дверьми с номерами меньше 6 находятся вообще младенцы (см. условие выше). А то, что нужно тебе, находится между 7-й и 11-й дверьми (включительно). Поэтому про двери  номерами, меньшими 7, забываешь. Делишь оставшийся отрезок (от 7 до 11) пополам, получаешь 9. Заходишь, там сидит бабушка 70-ти лет. Тебе это не подходит, причём очевидно, что за двери с номерами больше 9 лучше не заглядывать. Оставшиеся двери, которые нужно просмотреть: 7..8. За одной из этих дверей твоя красавица и сидит.


 
Мастер ©   (2004-11-19 12:26) [10]

 TFilteredList=class(TStringList)
 private
   FFilteredList:TStrings;
   FFilter: String;
   isFiltered: Boolean;
   procedure SetFiltered(const Value: Boolean);
   function GetCountFiltered: Integer;
   procedure ChangeFilter;
   procedure SetFilter(const Value: String);
   function GetFilteredItem(const index: Integer): String;
 public
   constructor Create;
   destructor Destroy; override;

   property Filter: String read FFilter write SetFilter;
   property CountFiltered: Integer read GetCountFiltered;
   property Filtered: Boolean read isFiltered write SetFiltered;
   property FilteredItems[const index: Integer]: String read GetFilteredItem;
   property FilteredList: TStrings read FFilteredList;
 end;

procedure TFilteredList.ChangeFilter;
var
 i: Integer;
 Len: Integer;
begin
 FFilteredList.Clear;
 if Filter="" then isFiltered := False;
 if not Filtered then Exit;
 Len := Length(FFilter);
 for i := 0 to Count-1 do
 begin
   if Copy(Self[i],1,Len)=FFilter then FFilteredList.Add(Self[i]);
 end;
end;

constructor TFilteredList.Create;
begin
 inherited Create;
 FFilteredList := TStringList.Create;
end;

destructor TFilteredList.Destroy;
begin
 FFilteredList.Free;
 inherited;
end;

function TFilteredList.GetCountFiltered: Integer;
begin
 Result := FFilteredList.Count;
end;

function TFilteredList.GetFilteredItem(const index: Integer): String;
begin
 Result := FFilteredList[index];
end;

procedure TFilteredList.SetFilter(const Value: String);
begin
 if FFilter=Value then Exit;
 FFilter := Value;
 ChangeFilter;
end;

procedure TFilteredList.SetFiltered(const Value: Boolean);
begin
 isFiltered := Value;
 ChangeFilter;
end;



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

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

Наверх




Память: 0.5 MB
Время: 0.031 c
3-1099983334
SDA
2004-11-09 09:55
2004.12.05
Что такое методы асинхронного коннекта???


3-1099813051
Dell3r
2004-11-07 10:37
2004.12.05
Remove Data Module


14-1100464788
SergP
2004-11-14 23:39
2004.12.05
Задачи для программистов. :-))


1-1101197302
denis24
2004-11-23 11:08
2004.12.05
for i:=0 to ScrollBox1.ControlCount-1


1-1100680324
Moiseev-KN
2004-11-17 11:32
2004.12.05
При запуске проги из Дельфи вылетает почему-то окно CPU