Текущий архив: 2006.03.05;
Скачать: CL | DM;
Вниз
аналог TList с полем Data Найти похожие ветки
← →
Piter © (2006-02-02 22:43) [0]Есть ли стандартный аналог TList с дополнительным полем Data (Object) для каждой записи? Ну типа TStringList, только хранятся Pointer (integer) + доп. массив Pointer (Object).
И еше было бы супер, если там фильтрация была, то есть:
TObj.Filter := 72
И чтобы в каком-нибудь поле остался только массив записей, значение которых равно 72
← →
Gero © (2006-02-02 22:45) [1]> Есть ли стандартный аналог TList с дополнительным полем
> Data (Object) для каждой записи?
Зачем если у тебя каждая запись и так Object? Размещай в нем что хочешь, какие проблемы?
> И чтобы в каком-нибудь поле
Каком поле?
← →
Джо © (2006-02-02 22:47) [2]TList позволяет хранить ссылку на любые данные. Что мешает хранить в нем указатель на запись (record), в которой и хранить это "дополнительное поле"?
← →
Piter © (2006-02-02 23:12) [3]Неудобно фильтровать по значению поля, придется пробегать весь лист при каждом новом значении фильтра. Возможно, есть способы поэффективнее.
← →
Lamer@fools.ua © (2006-02-02 23:14) [4]>Возможно, есть способы поэффективнее.
Один точно есть: написать свой класс с необходимой функциональностью :-)
← →
Gero © (2006-02-02 23:56) [5]> придется пробегать весь лист при каждом новом значении фильтра
Да, а ты думаешь, скажем IndexOf как-то по-другому работает?
Я именно так всегда и делаю.
← →
GuAV © (2006-02-03 00:24) [6]Думаю, нужно наследоваться от TList, в нём перекрыть notify и добавить приватное поле - ещё один такой же наследник, чтобы они ссылались друг на друга. А в notify - синхронизировать их изменения.
← →
Джо © (2006-02-03 03:11) [7]А я бы сделал как-то так.
unit SmartLst;
interface
uses SysUtils, Classes, Contnrs;
type
TSmartList = class
private
FList: TList;
FFiltered: TObjectList;
FFilter: Integer;
procedure SetFilter(const Value: Integer);
function GetCount: Integer;
function GetObjects(Index: Integer): TObject;
function GetItems(Index: Integer): Integer;
public
procedure Clear;
constructor Create;
destructor Destroy; override;
procedure Add (Item: Integer; Data: TObject); overload;
procedure Add (Item: Integer); overload;
property Items[Index: Integer]: Integer read GetItems; default;
property Objects[Index: Integer]: TObject read GetObjects;
property Count: Integer read GetCount;
property Filter: Integer read FFilter write SetFilter;
property Filtered: TObjectList read FFiltered;
end;
implementation
type
TListItem = record
Item: Integer;
Data: TObject;
end;
{ TSmartList }
procedure TSmartList.Add(Item: Integer; Data: TObject);
var
NewItem: ^TListItem;
begin
GetMem (NewItem,SizeOf(TListItem));
NewItem^.Item := Item;
NewItem^.Data := Data;
FList.Add(NewItem);
if (FFilter = 0) and (Item = 0) then
FFiltered.Add(Data);
end;
procedure TSmartList.Add(Item: Integer);
begin
Add (Item,nil)
end;
procedure TSmartList.Clear;
var
I: Integer;
begin
for I := 0 to FList.Count - 1 do
FreeMem(FList[I]);
FList.Clear
end;
constructor TSmartList.Create;
begin
FList := TList.Create;
FFiltered := TObjectList.Create(False);
end;
destructor TSmartList.Destroy;
begin
FList.Free;
FFiltered.Free;
inherited;
end;
function TSmartList.GetCount: Integer;
begin
Result := FList.Count
end;
function TSmartList.GetItems(Index: Integer): Integer;
begin
Result := TListItem(FList[Index]^).Item
end;
function TSmartList.GetObjects(Index: Integer): TObject;
begin
Result := TListItem(FList[Index]^).Data
end;
procedure TSmartList.SetFilter(const Value: Integer);
var
I: Integer;
begin
if Value = FFilter then
Exit;
FFiltered.Clear;
FFilter := Value;
for I := 0 to Count - 1 do
if GetItems(I) = Value then
FFiltered.Add(GetObjects(I))
end;
end.
И пользовался бы в таком духе:
procedure TForm18.Button1Click(Sender: TObject);
var
I: Integer;
SmartList: TSmartList;
begin
SmartList := TSmartList.Create;
try
SmartList.Add(5,TButton.Create(Self));
SmartList.Add(1,TLabel.Create(Self));
SmartList.Add(0,TEdit.Create(Self));
SmartList.Add(1,TListBox.Create(Self));
SmartList.Add(3,TComboBox.Create(Self));
// проверка фильтрации
SmartList.Filter := 1;
for I := 0 to SmartList.Filtered.Count - 1 do
ShowMessage (SmartList.Filtered[I].ClassName);
// проверка Items
for I := 0 to SmartList.Count - 1 do
ShowMessage (IntToStr(SmartList[I]));
// проверка Objects
for I := 0 to SmartList.Count - 1 do
ShowMessage ((SmartList.Objects[I].ClassName));
finally
SmartList.Free;
end;
end;
Если где-то закосячил, сорри, наспех состряпал.
← →
аноним (2006-02-03 07:59) [8]Джо © (03.02.06 03:11) [7]
отличный пример! взял на заметку.
← →
ЮЮ © (2006-02-03 08:02) [9]Удалено модератором
Примечание: Offtopic
← →
Джо © (2006-02-03 13:04) [10]
> [7] Джо ©
1. В Destroy забыл вставить Clear.
2. В Add(Item: Integer; Data: TObject); убрать 2 последние строки, они остались от предыдущего варианта.
← →
Джо © (2006-02-03 13:05) [11]3. В Clear нужно, наверное, также делать FFiltered.Clear.
Страницы: 1 вся ветка
Текущий архив: 2006.03.05;
Скачать: CL | DM;
Память: 0.48 MB
Время: 0.01 c